Browse Source

服务管理

vera_min 3 years ago
parent
commit
7be25a4d7f

+ 16 - 5
src/api/network/index.ts

@@ -2,15 +2,26 @@
  * @Author: vera_min vera_min@163.com
  * @Date: 2022-09-05 08:41:57
  * @LastEditors: vera_min vera_min@163.com
- * @LastEditTime: 2022-09-05 15:27:31
+ * @LastEditTime: 2022-09-06 17:18:17
  * @FilePath: /sagoo-admin-ui/src/api/network/index.ts
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  */
 import { get, post, del, put } from '/@/utils/request_network';
 
 export default {
-  getList: (params?: object) => get('/tunnel/list', params),
-  deleteItem: (params?: object) => del('/tunnel/delete', params),
-  getDetail: (params?: object) => get('/tunnel/get', params),
-  changeTunneStatus: (params?: object) => post('/tunnel/status', params),
+  tunnel: {
+    getList: (params?: object) => get('/tunnel/list', params),
+    deleteItem: (params?: object) => del('/tunnel/delete', params),
+    getDetail: (params?: object) => get('/tunnel/get', params),
+    changeTunnelStatus: (params?: object) => post('/tunnel/status', params),
+  
+  },
+  server: {
+    getList: (params?: object) => get('/server/list', params),
+    deleteItem: (params?: object) => del('/server/delete', params),
+    getDetail: (params?: object) => get('/get', params),
+    changeServerStatus: (params?: object) => post('/server/status', params),
+  
+  }
+
 }

+ 199 - 0
src/views/network/server/component/list.vue

@@ -0,0 +1,199 @@
+<template>
+    <div>
+        <el-table v-loading="loading" :data="data" style="width: 100%">
+            <el-table-column align="center" prop="id" label="ID" width="80"/>
+            <!-- <el-table-column align="center" prop="server" label="服务器"/> -->
+            <el-table-column align="center" prop="name" label="名称"/>
+            <el-table-column align="center" prop="types" label="类型"/>
+            <el-table-column align="center" prop="addr" label="地址"/>
+            <el-table-column show-overflow-tooltip align="center" prop="createdAt" label="创建时间" width="170"/>
+            <!-- <el-table-column align="center" prop="last" label="最近上线"/> -->
+            <el-table-column align="center" prop="types" label="状态">
+                <template #default="scope">
+                    <el-tag v-if="!scope.row.status" class="ml-2" type="danger">未启动</el-tag>
+                    <el-tag v-else class="ml-2" type="success">启动</el-tag>
+                </template>
+            </el-table-column>
+            <el-table-column align="center" label="操作" width="200">
+                <template #default="scope">
+                    
+                    <el-button @click="toDetail(scope.row.id)" size="small" type="text">详情</el-button>
+                    <el-button size="small" link key="info" type="info" @click="onOpenEditSign(scope.row)">编辑</el-button>
+                   
+                    <el-popover placement="bottom" :width="160" trigger="click">
+                        <template #reference>
+                            <el-button  size="small" type="text" class="more-btn" @click="isShowMore = !isShowMore">更多
+                                <i style="margin-left: 2px;" :class="isShowMore ? 'fa fa-angle-down':'fa fa-angle-up'"></i>
+                            </el-button>
+                        </template>
+                    <div class="more-opearte-wrap">
+                        <el-button @click="onChangeStatus(scope.row.id, 1)" :disabled="scope.row.status" link size="small" key="success" type="success">启 用</el-button>
+                        <el-divider direction="vertical" />
+                        <el-button @click="onChangeStatus(scope.row.id, 0)" :disabled="!scope.row.status" link size="small" key="warning" type="warning">禁 用</el-button>
+                        <el-divider direction="vertical" />
+                        <el-button @click="onRowDel(scope.row)" link size="small" key="danger" type="danger">删 除</el-button>
+                    </div>
+                    </el-popover>
+                </template>
+            </el-table-column>
+        </el-table>
+        <el-pagination
+            @size-change="onHandleSizeChange"
+            @current-change="onHandleCurrentChange"
+            class="mt15"
+            :pager-count="5"
+            :page-sizes="[10, 20, 30]"
+            v-model:current-page="param.page"
+            background
+            v-model:page-size="param.pageSize"
+            layout="total, sizes, prev, pager, next, jumper"
+            :total="total"
+        >
+        </el-pagination>
+    </div>
+    
+</template>
+
+<script lang="ts">
+import { ref, toRefs, reactive, onMounted, nextTick, computed, watch, defineComponent } from 'vue';
+import { ElMessageBox, ElMessage } from 'element-plus';
+import { useRouter } from 'vue-router';
+
+import api from '/@/api/network';
+
+// 定义接口来定义对象的类型
+interface TableDataForm {
+	id: number;
+    server: string;
+	name: string;
+	
+}
+interface TableData {
+	data:  Array<TableDataForm>;
+    total: number;
+    loading: boolean;
+    param: {
+        page: number;
+        pageSize: number;
+    };
+    isShowMore: boolean
+}
+
+export default defineComponent({
+    name: 'tunnel',
+	props: {
+		// 输入框前置内容
+		queryForm: {
+			type: Object,
+			default: () => {},
+		},
+    },
+    setup(props, { emit }) {
+        const router = useRouter();
+        const state = reactive<TableData>({
+			data: [],
+            total: 0,
+            loading: false,
+            param: {
+                page: 1,
+                pageSize: 10,
+            },
+            isShowMore: true
+            
+            
+		});
+        // 改变状态
+        const onChangeStatus = (id: number, status: number) => {
+            api.server.changeServerStatus({id: id, status: status}).then((res:any) => {
+		        ElMessage.success(status?'已开启':'已关闭');
+                fetchList();
+            })
+        };
+        // 分页改变
+		const onHandleSizeChange = (val: number) => {
+			state.param.pageSize = val;
+		};
+		// 分页改变
+		const onHandleCurrentChange = (val: number) => {
+			state.param.page = val;
+		};
+        // 初始化表格数据
+		const initTableData = () => {
+            fetchList()
+		};
+        // 获取数据
+        const fetchList = () => {
+            console.log(props.queryForm.title)
+            let params = {
+                searchKey: props.queryForm.title,
+                pageNum: state.param.page,
+                PageSize: state.param.pageSize
+            }
+            api.server.getList(params).then((res: any) => {
+				console.log(res);
+                const { list, total, page } = res
+                state.data = list
+                state.total = total
+                state.param.page = page
+			});
+
+
+		};
+        // 删除
+		const onRowDel = (row: TableDataForm) => {
+			ElMessageBox.confirm(`此操作将永久删除账户名称:“${row.name}”,是否继续?`, '提示', {
+				confirmButtonText: '确认',
+				cancelButtonText: '取消',
+				type: 'warning',
+			})
+				.then(() => {
+					api.server.deleteItem({ids: [row.id]}).then((res: any) => {
+						fetchList()
+						ElMessage.success('删除成功');
+					});
+				})
+				.catch(() => {});
+		};
+        const toDetail = (id: number) => {
+            router.push(`/network/server/detail/${id}`)
+        };
+        // 监听双向绑定 queryForm 的变化
+		watch(
+            () => props.queryForm,
+            // 新数据
+            () => {
+                fetchList()
+            },
+            {   deep: true,
+                immediate: true
+            },
+        );
+        // 页面加载时
+		onMounted(() => {
+			initTableData();
+		});
+        return {
+            fetchList,
+            toDetail,
+            onChangeStatus,
+            onRowDel,
+            onHandleSizeChange,
+            onHandleCurrentChange,
+            ...toRefs(state),
+        };
+    }
+});
+</script>
+
+<style lang="scss" scoped>
+::v-deep div.more-opearte-wrap {
+    flex-direction: row;
+    background-color: pink;
+    // padding: 4px!important;
+    div {
+       
+    }
+    
+}
+    
+</style>

+ 102 - 0
src/views/network/server/component/serverDetail.vue

@@ -0,0 +1,102 @@
+<!--
+ * @Author: vera_min vera_min@163.com
+ * @Date: 2022-09-05 08:41:57
+ * @LastEditors: vera_min vera_min@163.com
+ * @LastEditTime: 2022-09-06 17:18:19
+ * @FilePath: /sagoo-admin-ui/src/views/network/tunnel/component/serverDetail.vue
+ * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
+-->
+<!-- 服务器详情页 -->
+<template>
+	<div class="server-detail-wrap">
+        <div class="server-detail-item-wrap">
+            <div class="label">名称</div>
+            <div class="value">{{detail.name}}</div>
+        </div>
+        <div class="server-detail-item-wrap">
+            <div class="label">类型</div>
+            <div class="value">{{detail.types}}</div>
+        </div>
+        <div class="server-detail-item-wrap">
+            <div class="label">地址</div>
+            <div class="value">{{detail.addr}}</div>
+        </div>
+        <div class="server-detail-item-wrap">
+            <div class="label">状态</div>
+            <div class="value">{{detail.status?'启动':'未启动'}}</div>
+        </div>
+         <div class="server-detail-item-wrap">
+            <div class="label">禁用</div>
+            <div class="value">
+                <el-switch :loading="loading" :before-change="onChangeStatus" :disabled="!detail.status" :active-value="0"  :inactive-value="1" size="small" v-model="detail.status" />
+            </div>
+        </div>
+        <div class="server-detail-item-wrap">
+            <div class="label">创建时间</div>
+            <div class="value">{{detail.createdAt}}</div>
+        </div>
+    </div>
+</template>
+<script lang="ts">
+import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue';
+import { Delete, Edit, Search, Share, Upload } from '@element-plus/icons-vue';
+import { ElMessageBox, ElMessage } from 'element-plus';
+
+import api from '/@/api/network';
+
+interface TableDataState {
+	// detail: object,
+    loading: boolean
+}
+export default defineComponent({
+	name: 'serverDetail',
+	props: {
+		detail: {
+			type: Object,
+			default: ''
+		}
+	},
+	setup(props, context) {
+		const state = reactive<TableDataState>({
+            loading: false
+		});
+		onMounted(() => {
+            console.log(props.detail)
+		});
+        // 禁用状态
+        const onChangeStatus = () => {
+            state.loading = true
+            return new Promise((resolve) => {
+                api.server.changeServerStatus({id: props.detail.id, status: 0}).then((res:any) => {
+                state.loading = false
+		        ElMessage.success('已关闭');
+                props.detail.status = 0
+            })
+            })
+            
+        };
+		return {
+            onChangeStatus,
+			...toRefs(props),
+			...toRefs(state),
+		};
+	}
+});
+</script>
+
+<style lang="scss" scoped>
+.server-detail-wrap {
+    .server-detail-item-wrap {
+        display: flex;
+        justify-content: space-between;
+        padding: 10px;
+        border-left: 1px solid var(--el-border-color-light);
+        border-top: 1px solid var(--el-border-color-light);
+        border-right: 1px solid var(--el-border-color-light);
+    }
+    .server-detail-item-wrap:last-child {
+        border-bottom: 1px solid var(--el-border-color-light);
+    }
+}
+</style>
+

+ 202 - 0
src/views/network/server/component/table.vue

@@ -0,0 +1,202 @@
+<template>
+    <div class="container">
+        <!-- <el-table v-loading="loading" border stripe :data="data" style="width: 100%">
+            <el-table-column align="center" prop="id" label="ID"/>
+            <el-table-column align="center" prop="server" label="服务器"/>
+            <el-table-column align="center" prop="name" label="名称"/>
+            <el-table-column align="center" prop="types" label="类型"/>
+            <el-table-column align="center" prop="addr" label="地址"/>
+            <el-table-column show-overflow-tooltip align="center" prop="createdAt" label="创建时间"/>
+            <el-table-column align="center" prop="last" label="最近上线"/>
+            <el-table-column align="center" prop="types" label="状态">
+                <template #default="scope">
+                    <el-tag v-if="!scope.row.status" class="ml-2" type="danger">离线</el-tag>
+                    <el-tag v-else class="ml-2" type="success">在线</el-tag>
+                </template>
+            </el-table-column>
+            <el-table-column align="center" label="操作" width="200">
+                <template #default="scope">
+                    <el-button size="small" type="text" @click="onRowDel(scope.row)">详情</el-button>
+
+                    <el-button size="small" type="text" @click="onOpenEditSign(scope.row)">编辑</el-button>
+                    <el-button size="small" type="text" @click="onRowDetail(scope.row)">更多</el-button>
+                </template>
+            </el-table-column>
+        </el-table> -->
+        <div class="content">
+            <!-- <section v-for="(item, index) in data" :key="index"> -->
+            <el-card class="item" @click="toDetail(item.id)" shadow="hover" v-for="(item, index) in data" :key="index">
+                <div class="top-inner-wrap">
+                    <span>通道:{{item.id}}</span>
+                    <span class="more">更多
+                        <i class="fa fa-angle-down"></i>
+                        <!-- <ele-ArrowDown /> -->
+                    </span>
+                </div>
+                <div class="content-wrap">
+                    <div class="name-and-status">
+                        <span>{{item.name}}</span>
+                        [
+                        <span>{{item.status?'启动':'未启动'}}</span>
+                        ]
+                    </div>
+                    <div class="">
+                        <span>{{item.types}}</span>
+                        <span style="margin-left: 6px;">{{item.name}}</span>
+                    </div>
+                    
+                </div>
+            </el-card>
+        </div>
+        <el-pagination
+            @size-change="onHandleSizeChange"
+            @current-change="onHandleCurrentChange"
+            class="mt15"
+            :pager-count="5"
+            :page-sizes="[10, 20, 30]"
+            v-model:current-page="param.page"
+            background
+            v-model:page-size="param.pageSize"
+            layout="total, sizes, prev, pager, next, jumper"
+            :total="total"
+        >
+        </el-pagination>
+    </div>
+    
+</template>
+
+<script lang="ts">
+import { ref, toRefs, reactive, onMounted, nextTick, computed, watch, defineComponent } from 'vue';
+import { useRouter } from 'vue-router';
+import api from '/@/api/network';
+
+// 定义接口来定义对象的类型
+interface TableDataForm {
+	id: number;
+    server: string;
+	name: string;
+	
+}
+interface TableData {
+	data:  Array<TableDataForm>;
+    total: number;
+    loading: boolean;
+    param: {
+        page: number;
+        pageSize: number;
+    };
+}
+
+export default defineComponent({
+    name: 'tunnelTable',
+	props: {
+		// 输入框前置内容
+		queryForm: {
+			type: Object,
+			default: () => {},
+		},
+    },
+    setup(props, { emit }) {
+        const router = useRouter();
+        const state = reactive<TableData>({
+			data: [],
+            total: 0,
+            loading: false,
+            param: {
+                page: 1,
+                pageSize: 10,
+            },
+            
+            
+		});
+        // 分页改变
+		const onHandleSizeChange = (val: number) => {
+			state.param.pageSize = val;
+		};
+		// 分页改变
+		const onHandleCurrentChange = (val: number) => {
+			state.param.page = val;
+		};
+        // 初始化表格数据
+		const initTableData = () => {
+            console.log(props.queryForm.title)
+            let params = {
+                searchKey: props.queryForm.title,
+                pageNum: state.param.page,
+                PageSize: state.param.pageSize
+            }
+            api.server.getList(params).then((res: any) => {
+				console.log(res);
+                const { list, total, page } = res
+                state.data = list
+                state.total = total
+                state.param.page = page
+			});
+
+
+		};
+        const toDetail = (id: number) => {
+            router.push(`/network/server/detail/${id}`)
+        };
+        // 监听双向绑定 queryForm 的变化
+		watch(
+            () => props.queryForm,
+            // 新数据
+            () => {
+                initTableData()
+            },
+            {   deep: true,
+                immediate: true
+            },
+        );
+        // 页面加载时
+		onMounted(() => {
+			initTableData();
+		});
+        return {
+            toDetail,
+            onHandleSizeChange,
+            onHandleCurrentChange,
+            ...toRefs(state),
+        };
+    }
+});
+</script>
+
+<style lang="scss" scoped>
+.container {
+    width: 100%;
+    .content {
+        display: flex;
+        flex-flow: row wrap;
+        width: 100%;
+        .item {
+            width: calc((100% - 40px)/3);
+            cursor: pointer;
+            border-radius: 6px;
+            .top-inner-wrap {
+                font-size: 15px;
+                display: flex;
+                justify-content: space-between;
+                background: transparent;
+                border-bottom: 1px solid var(--el-card-border-color);
+                    // border: 1px solid var(--el-card-border-color);
+                .more {
+                    color: var(--el-color-primary);
+                }
+            }
+            .content-wrap {
+                .name-and-status {
+                    margin: 12px 0 8px 0;
+                }
+            }
+        }
+        .item:not(:nth-child(3n+1)) {
+            margin-left: 20px;
+        }
+        .item:nth-of-type(n+4) {
+            margin-top: 20px;
+        }
+    }
+}
+</style>

+ 254 - 0
src/views/network/server/create.vue

@@ -0,0 +1,254 @@
+<template>
+	<el-card class="system-dic-container" style="position: relative;">
+		<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
+			<el-tab-pane label="标准视图" name="first">
+				<el-collapse v-model="activeViewName">
+                    <el-collapse-item title="基本信息" name="1">
+                        <div class="collapse-wrap">
+                            <el-form style="width: 600px;margin: 0 auto;" :model="form" label-width="68px">
+                                <el-form-item label="名称">
+                                <el-input v-model="form.name" />
+                                </el-form-item>
+                                <el-form-item label="类型">
+                                <el-select v-model="form.region" placeholder="请选择类型">
+                                    <el-option label="Zone one" value="shanghai" />
+                                    <el-option label="Zone two" value="beijing" />
+                                </el-select>
+                                </el-form-item>
+                                <el-form-item label="禁用">
+                                    <el-switch style="--el-switch-on-color: #dc1414;" v-model="form.delivery" />
+                                </el-form-item>
+                            </el-form>
+                        </div>
+                    </el-collapse-item>
+                    <el-collapse-item title="串口参数" name="2">
+                        <div class="collapse-wrap">
+                            <el-form style="width: 600px;margin: 0 auto;" :model="form" label-width="68px">
+                                <el-form-item label="端口">
+                                    <el-button></el-button>
+                                </el-form-item>
+                                <el-form-item label="波特率">
+                                    <el-select v-model="form.region" placeholder="请选择波特率">
+                                        <el-option label="Zone one" value="shanghai" />
+                                        <el-option label="Zone two" value="beijing" />
+                                    </el-select>
+                                </el-form-item>
+                                <el-form-item label="数据位">
+                                    <el-select v-model="form.region" placeholder="请选择数据位">
+                                        <el-option label="Zone one" value="shanghai" />
+                                        <el-option label="Zone two" value="beijing" />
+                                    </el-select>
+                                </el-form-item>
+                                <el-form-item label="停止位">
+                                    <el-select v-model="form.region" placeholder="请选择停止位">
+                                        <el-option label="Zone one" value="shanghai" />
+                                        <el-option label="Zone two" value="beijing" />
+                                    </el-select>
+                                </el-form-item>
+                                <el-form-item label="检验位">
+                                    <el-select v-model="form.region" placeholder="请选择检验位">
+                                        <el-option label="Zone one" value="shanghai" />
+                                        <el-option label="Zone two" value="beijing" />
+                                    </el-select>
+                                </el-form-item>
+                            </el-form>
+                        </div>
+                    </el-collapse-item>
+                    <el-collapse-item title="断线重连" name="3">
+                        <el-form style="width: 600px;margin: 0 auto;" :model="form" label-width="68px">
+                            <el-form-item label="启用">
+                                <el-switch v-model="form.delivery" />
+                            </el-form-item>
+                            <el-form-item label="间隔">
+                                <el-input-number v-model="num" :min="1" :max="10" @change="handleChange" />
+                            </el-form-item>
+                            <el-form-item label="最大次数">
+                                <el-input-number v-model="num" :min="1" :max="10" @change="handleChange" />
+                            </el-form-item>
+                        </el-form>
+                    </el-collapse-item>
+                    <el-collapse-item title="协议适配" name="4">
+                        <el-form style="width: 600px;margin: 0 auto;" :model="form" label-width="68px">
+                            <el-form-item label="协议">
+                                <el-select v-model="form.region" placeholder="请选择协议适配">
+                                    <el-option label="Zone one" value="shanghai" />
+                                    <el-option label="Zone two" value="beijing" />
+                                </el-select>
+                            </el-form-item>
+                            <el-form-item label="协议参数">
+                                
+                                <codeEditor class="params" ref="mirrorRef"
+                                :mode="resourceModalPro.mode"
+                                :content="resourceModalPro.content"
+                                >
+                                </codeEditor>
+                            </el-form-item>
+                        </el-form>
+                    </el-collapse-item>
+                </el-collapse>
+			</el-tab-pane>
+			<el-tab-pane label="专家视图" name="second">
+                <h1>专家视图</h1>
+            </el-tab-pane>
+		</el-tabs>
+		<div style="position: absolute;right:20px;top: 34px;">
+			<el-icon style="font-size: 16px;"><ele-RefreshRight /></el-icon>
+			<el-icon style="font-size: 16px;margin: 0 6px;"><ele-Operation /></el-icon>
+			<el-icon style="font-size: 16px;"><ele-Edit /></el-icon>
+		</div>
+
+	  	 <!-- <codeEditor ref="mirrorRef"
+	  :mode="resourceModalPro.mode"
+	  :content="resourceModalPro.content"
+	  >
+	  </codeEditor> -->
+	</el-card>
+</template>
+<script lang="ts">
+import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue';
+import { Delete, Edit, Search, Share, Upload } from '@element-plus/icons-vue';
+import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
+import type { TabsPaneContext } from 'element-plus'
+import codeEditor from '/@/components/codeEditor/index.vue'
+
+import serverDetail from './component/serverDetail.vue'
+
+import { useRoute } from 'vue-router';
+
+import api from '/@/api/network';
+
+interface TableDataState {
+	// ids: number[];
+	// id: string;
+    activeViewName: string[];
+	resourceModalPro: {
+		mode: string,
+		content: string,
+		// content: object,
+	},
+	detail: object,
+    form: object
+}
+export default defineComponent({
+	name: 'tunnelCreate',
+	components: { codeEditor, serverDetail },
+	props: {
+		type: {
+			type: String,
+			default: ''
+		}
+	},
+
+	setup(props, context) {
+		const route = useRoute();
+		const state = reactive<TableDataState>({
+            // id: "",
+			resourceModalPro: {
+				mode: '',
+				content: ''
+			},
+			detail:{},
+            activeViewName: ['1','2','3','4'],
+            form:{
+                name: '',
+                region: '',
+                date1: '',
+                date2: '',
+                delivery: false,
+                type: [],
+                resource: '',
+                desc: '',
+            }
+		});
+		const activeName = ref('first')
+        // const activeViewName = ref('1')
+		const getDetail = () => {
+			const id = route.params && route.params.id;
+			api.server.getDetail({"id": id}).then((res: any) => {
+				console.log(res)
+				state.detail = res
+			})
+		};
+		onMounted(() => {
+			// return;
+			let obj = {
+						"id": 1,
+						"name": "新建服务器",
+						"type": "tcp",
+						"addr": "10010",
+						"register": {
+							"regex": "^\\w+$"
+						},
+						"heartbeat": {
+							"enable": false,
+							"timeout": 30,
+							"regex": "^\\w+$"
+						},
+						"protocol": {
+							"name": "ModbusTCP",
+							"options": {}
+						},
+						"devices": [
+							{
+								"station": 1,
+								"product_id": ""
+							}
+						],
+						"disabled": false,
+						"updated": "2022-08-26T15:10:07+08:00",
+						"created": "2022-08-20T18:44:20+08:00",
+						"running": true
+					}
+					var jsonData = JSON.stringify(obj);//data是请求的后台数据
+					state.resourceModalPro.content = JSON.stringify(JSON.parse(jsonData),null,4);
+		});
+		const handleClick = (tab: TabsPaneContext, event: Event) => {
+			console.log(tab, event)
+		}
+
+		return {
+			Edit,
+			activeName,
+			getDetail,
+			handleClick,
+			// editDicRef,
+			// editAttrRef,
+			// editFunRef,
+			// editEventRef,
+			// editTabRef,
+			...toRefs(props),
+			...toRefs(state),
+		};
+	},
+});
+</script>
+
+<style>
+.CodeMirror {
+  width: 100%;
+  height: 600px;
+  font-size: 16px;
+}
+</style>
+<style lang="scss" scoped>
+::v-deep .el-collapse-item__header {
+    position: relative;
+    padding-left: 20px;
+    .el-collapse-item__arrow {
+        margin: 0!important;
+        position: absolute;
+        left: 0;
+        right: 0;
+        
+    }
+}
+::v-deep .el-input,
+::v-deep .el-input-number {
+    width: 500px;
+}
+::v-deep .params {
+    width: 600px;
+}
+
+</style>
+

+ 138 - 0
src/views/network/server/detail.vue

@@ -0,0 +1,138 @@
+<template>
+	<el-card class="system-dic-container" style="position: relative;">
+		<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
+			<el-tab-pane label="服务器详情" name="first">
+				<serverDetail :detail="detail" />
+			</el-tab-pane>
+			<el-tab-pane label="相关详情" name="second">相关详情</el-tab-pane>
+			<el-tab-pane label="通道" name="third">通道</el-tab-pane>
+		</el-tabs>
+		<div style="position: absolute;right:20px;top: 34px;">
+			<el-icon style="font-size: 16px;"><ele-RefreshRight /></el-icon>
+			<el-icon style="font-size: 16px;margin: 0 6px;"><ele-Operation /></el-icon>
+			<el-icon style="font-size: 16px;"><ele-Edit /></el-icon>
+		</div>
+
+	  	 <!-- <codeEditor ref="mirrorRef"
+	  :mode="resourceModalPro.mode"
+	  :content="resourceModalPro.content"
+	  >
+	  </codeEditor> -->
+	</el-card>
+</template>
+<script lang="ts">
+import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue';
+import { Delete, Edit, Search, Share, Upload } from '@element-plus/icons-vue';
+import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
+import type { TabsPaneContext } from 'element-plus'
+import codeEditor from '/@/components/codeEditor/index.vue'
+
+import serverDetail from './component/serverDetail.vue'
+
+import { useRoute } from 'vue-router';
+
+import api from '/@/api/network';
+
+interface TableDataState {
+	// ids: number[];
+	// id: string;
+	resourceModalPro: {
+		mode: string,
+		content: string,
+		// content: object,
+	},
+	detail: {}
+}
+export default defineComponent({
+	name: 'tunnelDetail',
+	components: { codeEditor, serverDetail },
+	props: {
+		type: {
+			type: String,
+			default: ''
+		}
+	},
+
+	setup(props, context) {
+		const route = useRoute();
+		const state = reactive<TableDataState>({
+            // id: "",
+			resourceModalPro: {
+				mode: '',
+				content: ''
+			},
+			detail:{}
+		});
+		const activeName = ref('first')
+		const getDetail = () => {
+			const id = route.params && route.params.id;
+			api.server.getDetail({"id": id}).then((res: any) => {
+				console.log(res)
+				state.detail = res
+			})
+		};
+		onMounted(() => {
+			// state.id = route.params && route.params.id;
+			// console.log(state.id)
+			getDetail()
+			return;
+			let obj = {
+						"id": 1,
+						"name": "新建服务器",
+						"type": "tcp",
+						"addr": "10010",
+						"register": {
+							"regex": "^\\w+$"
+						},
+						"heartbeat": {
+							"enable": false,
+							"timeout": 30,
+							"regex": "^\\w+$"
+						},
+						"protocol": {
+							"name": "ModbusTCP",
+							"options": {}
+						},
+						"devices": [
+							{
+								"station": 1,
+								"product_id": ""
+							}
+						],
+						"disabled": false,
+						"updated": "2022-08-26T15:10:07+08:00",
+						"created": "2022-08-20T18:44:20+08:00",
+						"running": true
+					}
+					var jsonData = JSON.stringify(obj);//data是请求的后台数据
+					state.resourceModalPro.content = JSON.stringify(JSON.parse(jsonData),null,4);
+		});
+		const handleClick = (tab: TabsPaneContext, event: Event) => {
+			console.log(tab, event)
+		}
+
+		return {
+			Edit,
+			activeName,
+			getDetail,
+			handleClick,
+			// editDicRef,
+			// editAttrRef,
+			// editFunRef,
+			// editEventRef,
+			// editTabRef,
+			...toRefs(props),
+			...toRefs(state),
+		};
+	},
+});
+</script>
+
+<style>
+.CodeMirror {
+  width: 100%;
+  height: 600px;
+  font-size: 16px;
+}
+</style>
+

+ 121 - 0
src/views/network/server/index.vue

@@ -0,0 +1,121 @@
+<template>
+    <div class="container">
+        <el-card shadow="hover">
+            <div class="top-operate-wrap">
+                <div class="left">
+                    <el-button @click="toPage" size="default" type="success" class="ml10">
+                        <el-icon>
+                            <ele-FolderAdd />
+                        </el-icon>
+                        新建
+                    </el-button>
+                    <el-input size="default" style="width: 200px;margin-left: 20px;" class="search-input" v-model="key" placeholder="请输入搜索关键字" clearable>
+                    </el-input>
+                    <el-button  type="primary" plain size="default" @click="searchData">搜索</el-button>
+                </div>
+                <div class="right">  
+                    <el-button @click="index=1" :class="index==1?'active':''" size="default" class="fa fa-th"></el-button>
+                    <el-button @click="index=2" :class="index==2?'active':''" size="default" class="fa fa-list"></el-button>
+                </div>        
+            </div>
+            <!-- 页面主要内容 -->
+            <tempalte v-if="index==1">
+                <!-- table -->
+                <tableTunnel :queryForm="queryParams" />
+
+            </tempalte>
+
+            <tempalte v-if="index==2">
+                <!-- list -->
+                <listTunnel :queryForm="queryParams" />
+
+            </tempalte>
+
+        </el-card>
+        
+    </div>
+</template>
+
+<script lang="ts">
+import { reactive, toRefs, onMounted, defineComponent, ref } from 'vue';
+import type { FormInstance, FormRules } from 'element-plus';
+import { useRouter } from 'vue-router';
+import { ElMessage } from 'element-plus';
+
+import listTunnel from './component/list.vue';
+import tableTunnel from './component/table.vue';
+
+// import api from '/@/api/assess';
+
+
+// 定义接口来定义对象的类型
+interface RuleFormRow {
+    title: string;
+	
+}
+
+interface ItemState {
+	queryParams: RuleFormRow;
+    index: number;
+    key: string;
+}
+
+export default defineComponent({
+    name: 'tunnalManage',
+    components: { listTunnel, tableTunnel },
+	setup() {
+        const router = useRouter();
+		const state = reactive<ItemState>({
+            index: 2,
+			queryParams: {
+                title: ''
+			},
+            key: ''
+		});
+        const searchData = () => {
+            console.log(state.key)
+            state.queryParams.title = state.key
+        };
+        const toPage = () => {
+            router.push('/network/tunnel/create')
+        };
+        return {
+            toPage,
+            searchData,
+			...toRefs(state),
+		};
+    },
+    
+});
+</script>
+
+<style lang="scss" scoped>
+.container {
+    .top-operate-wrap {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-bottom: 20px;
+        .left,
+        .right {
+            display: flex;
+            .el-button:nth-child(2) {
+                margin-left: 0;
+                border-top-left-radius: 0;
+                border-bottom-left-radius: 0;
+            }
+            .el-button:nth-child(1) {
+               border-top-right-radius: 0;
+                border-bottom-right-radius: 0;
+                border-right: none;
+            }
+            .active {
+                color: var(--el-button-hover-text-color);
+                border-color: var(--el-button-hover-border-color);
+                background-color: var(--el-button-hover-bg-color);
+                outline: 0;
+            }
+        }
+    }
+}
+</style>

+ 4 - 4
src/views/network/tunnel/component/list.vue

@@ -1,6 +1,6 @@
 <template>
     <div>
-        <el-table v-loading="loading" border stripe :data="data" style="width: 100%">
+        <el-table v-loading="loading" :data="data" style="width: 100%">
             <el-table-column align="center" prop="id" label="ID" width="80"/>
             <!-- <el-table-column align="center" prop="server" label="服务器"/> -->
             <el-table-column align="center" prop="name" label="名称"/>
@@ -104,7 +104,7 @@ export default defineComponent({
 		});
         // 改变状态
         const onChangeStatus = (id: number, status: number) => {
-            api.changeTunneStatus({id: id, status: status}).then((res:any) => {
+            api.tunnel.changeTunnelStatus({id: id, status: status}).then((res:any) => {
 		        ElMessage.success(status?'已开启':'已关闭');
                 fetchList();
             })
@@ -129,7 +129,7 @@ export default defineComponent({
                 pageNum: state.param.page,
                 PageSize: state.param.pageSize
             }
-            api.getList(params).then((res: any) => {
+            api.tunnel.getList(params).then((res: any) => {
 				console.log(res);
                 const { list, total, page } = res
                 state.data = list
@@ -147,7 +147,7 @@ export default defineComponent({
 				type: 'warning',
 			})
 				.then(() => {
-					api.deleteItem({ids: [row.id]}).then((res: any) => {
+					api.tunnel.deleteItem({ids: [row.id]}).then((res: any) => {
 						fetchList()
 						ElMessage.success('删除成功');
 					});

+ 3 - 3
src/views/network/tunnel/component/serverDetail.vue

@@ -2,7 +2,7 @@
  * @Author: vera_min vera_min@163.com
  * @Date: 2022-09-05 08:41:57
  * @LastEditors: vera_min vera_min@163.com
- * @LastEditTime: 2022-09-05 19:56:59
+ * @LastEditTime: 2022-09-06 17:18:49
  * @FilePath: /sagoo-admin-ui/src/views/network/tunnel/component/serverDetail.vue
  * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 -->
@@ -63,11 +63,11 @@ export default defineComponent({
 		onMounted(() => {
             console.log(props.detail)
 		});
-        // 禁用操作
+        // 禁用状态
         const onChangeStatus = () => {
             state.loading = true
             return new Promise((resolve) => {
-                api.changeTunneStatus({id: props.detail.id, status: 0}).then((res:any) => {
+                api.tunnel.changeTunnelStatus({id: props.detail.id, status: 0}).then((res:any) => {
                 state.loading = false
 		        ElMessage.success('已关闭');
                 props.detail.status = 0

+ 1 - 1
src/views/network/tunnel/component/table.vue

@@ -125,7 +125,7 @@ export default defineComponent({
                 pageNum: state.param.page,
                 PageSize: state.param.pageSize
             }
-            api.getList(params).then((res: any) => {
+            api.tunnel.getList(params).then((res: any) => {
 				console.log(res);
                 const { list, total, page } = res
                 state.data = list

+ 1 - 1
src/views/network/tunnel/create.vue

@@ -164,7 +164,7 @@ export default defineComponent({
         // const activeViewName = ref('1')
 		const getDetail = () => {
 			const id = route.params && route.params.id;
-			api.getDetail({"id": id}).then((res: any) => {
+			api.tunnel.getDetail({"id": id}).then((res: any) => {
 				console.log(res)
 				state.detail = res
 			})

+ 1 - 1
src/views/network/tunnel/detail.vue

@@ -66,7 +66,7 @@ export default defineComponent({
 		const activeName = ref('first')
 		const getDetail = () => {
 			const id = route.params && route.params.id;
-			api.getDetail({"id": id}).then((res: any) => {
+			api.tunnel.getDetail({"id": id}).then((res: any) => {
 				console.log(res)
 				state.detail = res
 			})