picasso 3 gadi atpakaļ
vecāks
revīzija
d2be9e56d0

+ 48 - 0
package-lock.json

@@ -1019,6 +1019,39 @@
       "resolved": "https://registry.npmmirror.com/blueimp-canvastoblob/-/blueimp-canvastoblob-2.1.0.tgz",
       "integrity": "sha512-XExr0EIfB/ugmmrht7mcq4h5UXCaaC37jFF3m0h0WCBayku3Q9Hm227tCCDuGvD74/HIKJJ6xEoDJVHjdMcQ0g=="
     },
+    "bmaplib.curveline": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/bmaplib.curveline/-/bmaplib.curveline-1.0.0.tgz",
+      "integrity": "sha512-9wcFMVhiYxNPqpvsLDAADn3qDhNzXp2mA6VyHSHg2XOAgSooC7ZiujdFhy0sp+0QYjTfJ/MjmLuNoUg2HHxH4Q=="
+    },
+    "bmaplib.distancetool": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/bmaplib.distancetool/-/bmaplib.distancetool-1.0.2.tgz",
+      "integrity": "sha512-EvxMnQRH6xM036zx5OLPyTg5tMCTbFBuGTTHOtExLy2/T0X6v5Va0YE7c3IPm/a/Eo5V/ynYpOLOLZbRY8ccyA=="
+    },
+    "bmaplib.heatmap": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmmirror.com/bmaplib.heatmap/-/bmaplib.heatmap-1.0.4.tgz",
+      "integrity": "sha512-rmhqUARBpUSJ9jXzUI2j7dIOqnc38bqubkx/8a349U2qtw/ulLUwyzRD535OrA8G7w5cz4aPKm6/rNvUAarg/Q=="
+    },
+    "bmaplib.lushu": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmmirror.com/bmaplib.lushu/-/bmaplib.lushu-1.0.7.tgz",
+      "integrity": "sha512-LVvgpESPii6xGxyjnQjq8u+ic4NjvhdCPV/RiSS/PGTUdZKeTDS7prSpleJLZH3ES0+oc0gYn8bw0LtPYUSz2w=="
+    },
+    "bmaplib.markerclusterer": {
+      "version": "1.0.13",
+      "resolved": "https://registry.npmmirror.com/bmaplib.markerclusterer/-/bmaplib.markerclusterer-1.0.13.tgz",
+      "integrity": "sha512-VrLyWSiuDEVNi0yUfwOhFQ6z1oEEHS4w36GNu3iASu6p52QIx9uAXMUkuSCHReNR0bj2Cp9SA1dSx5RpojXajQ==",
+      "requires": {
+        "bmaplib.texticonoverlay": "^1.0.2"
+      }
+    },
+    "bmaplib.texticonoverlay": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/bmaplib.texticonoverlay/-/bmaplib.texticonoverlay-1.0.2.tgz",
+      "integrity": "sha512-4ZTWr4ZP3B6qEWput5Tut16CfZgII38YwM3bpyb4gFTQyORlKYryFp9WHWrwZZaHlOyYDAXG9SX0hka43jTADg=="
+    },
     "boolbase": {
       "version": "1.0.0",
       "resolved": "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz",
@@ -3549,6 +3582,21 @@
         "@vue/shared": "3.2.37"
       }
     },
+    "vue-baidu-map-3x": {
+      "version": "1.0.18",
+      "resolved": "https://registry.npmmirror.com/vue-baidu-map-3x/-/vue-baidu-map-3x-1.0.18.tgz",
+      "integrity": "sha512-02KmFBLZ7xr/rmolRTo2tXw/uN3C0sYCag0D4RENkzggB2kHlKSijf+HLiedgNRDogfeS9IQkwo8zOhYIHga9A==",
+      "requires": {
+        "bmaplib.curveline": "^1.0.0",
+        "bmaplib.distancetool": "^1.0.2",
+        "bmaplib.heatmap": "^1.0.4",
+        "bmaplib.lushu": "^1.0.7",
+        "bmaplib.markerclusterer": "^1.0.13",
+        "tiny-emitter": "^2.1.0",
+        "vue": "^3.2.25",
+        "vue-router": "^4.0.14"
+      }
+    },
     "vue-clipboard3": {
       "version": "1.0.1",
       "resolved": "https://registry.npmmirror.com/vue-clipboard3/-/vue-clipboard3-1.0.1.tgz",

+ 2 - 1
package.json

@@ -32,6 +32,7 @@
     "sortablejs": "^1.14.0",
     "splitpanes": "^3.1.1",
     "vue": "^3.2.37",
+    "vue-baidu-map-3x": "^1.0.18",
     "vue-clipboard3": "^1.0.1",
     "vue-grid-layout": "^3.0.0-beta1",
     "vue-i18n": "9.1.10",
@@ -82,4 +83,4 @@
     "type": "git",
     "url": "https://gitee.com/lyt-top/vue-next-admin.git"
   }
-}
+}

+ 20 - 0
src/api/heatStation/index.ts

@@ -0,0 +1,20 @@
+import { get, post, del, put } from '/@/utils/request';
+
+export default {
+  loop: {
+    getList: (params: object) => get('/region/loop/list', params),
+    add: (data: object) => post('/region/loop/add', data),
+    edit: (data: object) => post('/region/loop/edit', data),
+    // getLists: (params: object) => get('/product/list', params),
+    // delete: (ids: number) => del('/product/del', { ids }),
+    // edit: (data: object) => put('/product/edit', data),
+    // detail: (id: number) => get('/product/detail', { id }),
+  },
+  heatStation: {
+    getList: (params: object) => get('/region/heatStation/tree', params),
+    add: (data: object) => post('/region/heatStation/add', data),
+    edit: (data: object) => post('/region/heatStation/edit', data),
+    // delete: (ids: number) => del('/product/del', { ids }),
+    // detail: (id: number) => get('/product/detail', { id }),
+  }
+}

+ 4 - 1
src/main.ts

@@ -1,4 +1,5 @@
 import { createApp } from 'vue';
+import Vue from 'vue';
 import App from './App.vue';
 import router from './router';
 import { store, key } from './store';
@@ -17,6 +18,8 @@ import { useDict } from "/@/api/common/dict/data";
 import pagination from '/@/components/pagination/index.vue'
 import 'amis/sdk/sdk.js';
 import 'amis/lib/themes/default.css';
+// 引入百度地图组件
+import BaiduMap from 'vue-baidu-map-3x'
 
 const app = createApp(App);
 
@@ -24,12 +27,12 @@ directive(app);
 other.elSvg(app);
 
 app.component('pagination', pagination)
-
 app.use(router)
     .use(store, key)
     .use(ElementPlus, { i18n: i18n.global.t })
     .use(i18n)
     .use(VueGridLayout)
+    .use(BaiduMap, { ak: 'Kp8XHK81HSF6rfRkYP7OxYKtK8IaG51d' })
     .mount('#app');
 
 // 全局挂载

+ 77 - 0
src/views/heatStation/heatStation/component/detail.vue

@@ -0,0 +1,77 @@
+<template>
+	<div class="system-edit-dic-container">
+		<el-dialog title="查看设备" v-model="isShowDialog" width="769px">
+			<el-form :model="ruleForm" ref="formRef" :rules="rules" size="default" label-width="110px">
+				<el-form-item label="设备标识" prop="key">
+					{{ ruleForm.key }}
+				</el-form-item>
+				<el-form-item label="设备名称" prop="name">
+					{{ ruleForm.name }}
+				</el-form-item>
+
+				<el-form-item label="所属产品" prop="productId">
+					{{ ruleForm.productName }}
+				</el-form-item>
+
+				<el-form-item label="所属部门" prop="deptId">
+					{{ ruleForm.deptName }}
+				</el-form-item>
+
+				<el-form-item label="设备证书" prop="certificate">
+					{{ ruleForm.certificate }}
+				</el-form-item>
+
+				<el-form-item label="设备秘钥" prop="secureKey">
+					{{ ruleForm.secureKey }}
+				</el-form-item>
+
+				<el-form-item label="固件版本号" prop="version">
+					{{ ruleForm.version }}
+				</el-form-item>
+
+				<el-form-item label="备注" prop="desc">
+					{{ ruleForm.desc }}
+				</el-form-item>
+			</el-form>
+		</el-dialog>
+	</div>
+</template>
+
+<script lang="ts">
+import { reactive, toRefs, defineComponent, ref, unref } from 'vue';
+import api from '/@/api/device';
+import { ElMessage } from 'element-plus';
+
+
+export default defineComponent({
+	name: 'deviceEditPro',
+	setup(prop, { emit }) {
+		const state = reactive({
+			isShowDialog: false,
+			ruleForm: {}
+		});
+		// 打开弹窗
+		const openDialog = (row: any) => {
+			if (row) {
+				state.ruleForm = row;
+			}
+			state.isShowDialog = true;
+		};
+
+		// 关闭弹窗
+		const closeDialog = () => {
+			state.isShowDialog = false;
+		};
+		// 取消
+		const onCancel = () => {
+			closeDialog();
+		};
+		return {
+			openDialog,
+			closeDialog,
+			onCancel,
+			...toRefs(state),
+		};
+	},
+});
+</script>

+ 208 - 0
src/views/heatStation/heatStation/component/edit.vue

@@ -0,0 +1,208 @@
+<template>
+	<div class="system-edit-dic-container">
+		<el-dialog :title="(ruleForm.id !== 0 ? '修改' : '添加') + '换热站'" v-model="dialogVisible" width="769px">
+			<el-form :model="ruleForm" ref="formRef" :rules="rules" size="default" label-width="110px">
+				<el-form-item label="上级换热站" prop="">
+					<el-tree-select
+						v-model="ruleForm.parentId"
+						:data="treeData"
+						:props="{
+							label: 'name',
+							children: 'children'
+						}"
+						node-key="id"
+						:clearable="true"
+						check-strictly
+						style="width: 100%;"
+						:render-after-expand="true"
+					/>
+				</el-form-item>
+				<el-form-item label="换热站名称" prop="name">
+					<el-input v-model="ruleForm.name" placeholder="请输入换热站名称" />
+				</el-form-item>
+				<!-- <el-form-item label="换热站编号" prop="code">
+					<el-input v-model="ruleForm.code" placeholder="请输入换热站编号" />
+				</el-form-item> -->
+				<el-form-item label="换热站位置" prop="position">
+					<el-input v-model="ruleForm.position" placeholder="请输入换热站位置" />
+				</el-form-item>
+				<el-form-item label="负责人" prop="principal">
+					<el-input v-model="ruleForm.principal" placeholder="请输入负责人" />
+				</el-form-item>
+				<el-form-item label="状态" prop="status">
+					<el-radio v-model="ruleForm.status" :label="1">在线</el-radio>
+					<el-radio v-model="ruleForm.status" :label="0">不在线</el-radio>
+				</el-form-item>
+        <el-form-item label="地图展示" prop="decade">
+					<div class="mb10" style="width: 100%">
+						<el-input v-model="ruleForm.keyword" placeholder="请输入关键字进行搜索" clearable style="width: 100%;"></el-input>
+						<!-- <span class="mr10">经度</span>
+						<el-input v-model="ruleForm.lnt" style="width: 120px" class="mr10" placeholder="经度"></el-input>
+						<span class="mr10">纬度</span>
+						<el-input v-model="ruleForm.lat" style="width: 120px" placeholder="纬度"></el-input> -->
+					</div>
+          <baidu-map class="map" :center="{ lng: ruleForm.lnt, lat: ruleForm.lat }" :scroll-wheel-zoom="true" :zoom="15" style="width: 100%; height: 300px" @click="onMapClick">
+            <bm-navigation anchor="BMAP_ANCHOR_TOP_RIGHT"></bm-navigation>
+						<bm-local-search :keyword="ruleForm.keyword" :panel="false" :auto-viewport="true" @markersset="onMarkersset"></bm-local-search>
+          </baidu-map>
+        </el-form-item>
+			</el-form>
+			<template #footer>
+				<span class="dialog-footer">
+					<el-button @click="onCancel" size="default">取 消</el-button>
+					<el-button type="primary" @click="onSubmit" size="default">{{ ruleForm.id !== 0 ? '修 改' : '添 加' }}</el-button>
+				</span>
+			</template>
+		</el-dialog>
+	</div>
+</template>
+
+<script lang="ts">
+import { reactive, toRefs, defineComponent, ref, unref, nextTick } from 'vue';
+import api from '/@/api/heatStation';
+import { ElMessage } from 'element-plus';
+import { Console } from 'console';
+interface RuleFormState {
+	id: number;
+	parentId: number | string;
+	name: string;
+	position: string;
+	lnt: number;
+	lat: number;
+	principal: string;
+	types: number;
+	status: number;
+}
+
+export default defineComponent({
+	name: 'headStationLoop',
+	setup(prop, { emit }) {
+		const formRef = ref<HTMLElement | null>(null);
+		const state = reactive({
+			dialogVisible: false,
+			ruleForm: {
+				id: 0,
+				parentId: '',
+				name: '',
+				position: '',
+				lnt: 116.404,
+				lat: 39.915,
+				principal: '',
+				types: 1,
+				status: 1
+			},
+			rules: {
+				name: [{ required: true, message: '换热站名称不能为空', trigger: 'blur' }],
+				position: [{ required: true, message: '换热站位置不能为空', trigger: 'blur' }],
+				principal: [{ required: true, message: '负责人不能为空', trigger: 'blur' }],
+				status: [{ required: true, message: '状态不能为空', trigger: 'blur' }]
+			},
+			treeData: [],
+			mapResult: [] // 地图搜索点结果
+		})
+		// 打开弹窗
+		const openDialog = (row: any, tree: any) => {
+			resetForm()
+			state.treeData = tree
+			// nextTick(() => {
+			// 	let BMap = (window as any).BMap
+			// 	if (BMap) {
+			// 		let geolocation = new BMap.Geolocation();//返回用户当前的位置
+			// 		geolocation.getCurrentPosition(function(r: any) {
+			// 			console.log(r)
+			// 			state.center.lat = r.latitude
+			// 			state.center.lng = r.longitude
+			// 			// latitude: 22.322230460245
+			// 			// longitude: 114.1808934593
+			// 		});
+			// 	}
+			// }) 
+
+			if (row) {
+				state.ruleForm = {
+					...row,
+					parentId: row.parentId === -1 ? '' : row.parentId
+				}
+			}
+			state.dialogVisible = true
+		}
+		const resetForm = () => {
+			state.ruleForm = {
+				id: 0,
+				parentId: '',
+				name: '',
+				// code: '',
+				position: '',
+				lnt: 116.404,
+				lat: 39.915,
+				principal: '',
+				types: 1,
+				status: 1
+			}
+		}
+		// 关闭弹窗
+		const closeDialog = () => {
+			state.dialogVisible = false
+		}
+		// 取消
+		const onCancel = () => {
+			closeDialog()
+		}
+		// 新增
+		const onSubmit = () => {
+			const formWrap = unref(formRef) as any
+			if (!formWrap) return;
+			formWrap.validate((valid: boolean) => {
+				if (valid) {
+					let params = { ...state.ruleForm };
+					(params.parentId as any) = params.parentId || -1
+					if (state.ruleForm.id) {
+						//修改
+						api.heatStation.edit(params).then(() => {
+							ElMessage.success('换热站修改成功')
+							closeDialog() // 关闭弹窗
+							emit('querylist')
+						})
+					} else {
+						//添加
+						api.heatStation.add(params).then(() => {
+							ElMessage.success('换热站添加成功')
+							closeDialog() // 关闭弹窗
+							emit('querylist')
+						})
+					}
+				}
+			})
+		}
+		const onMapClick = (e: any) => {
+			console.log('onMapClick', e)
+			console.log('onMapClick', e.QA.K.title)
+			console.log(state.mapResult.find((item: any) => item.marker.da) === e.currentTarget.da)
+		}
+		const onMarkersset = (e: any) => {
+			console.log('onMarkersset', e)
+			state.mapResult = e
+		}
+
+		return {
+			openDialog,
+			closeDialog,
+			onCancel,
+			onSubmit,
+			formRef,
+			onMapClick,
+			onMarkersset,
+			...toRefs(state)
+		}
+	}
+})
+</script>
+
+<style scoped lang="scss">
+.mb10 {
+	margin-bottom: 10px;
+}
+.mr10 {
+	margin-right: 10px;
+}
+</style>

+ 198 - 0
src/views/heatStation/heatStation/index.vue

@@ -0,0 +1,198 @@
+<template>
+  <div class="system-dic-container">
+    <el-card shadow="hover">
+      <div class="system-user-search mb15">
+        <el-form :model="tableData.param" ref="queryRef" :inline="true" label-width="100px">
+          <el-form-item label="换热站名称" prop="name">
+            <el-input v-model="tableData.param.name" placeholder="请输入换热站名称" clearable size="default" @keyup.enter="queryList" />
+          </el-form-item>
+		  		<el-form-item label="换热站编号" prop="code">
+            <el-input v-model="tableData.param.code" placeholder="请输入换热站编号" clearable size="default" @keyup.enter="queryList" />
+          </el-form-item>
+          <el-form-item>
+            <el-button size="default" type="primary" class="ml10" @click="queryList">
+              <el-icon>
+                <ele-Search />
+              </el-icon>
+              查询
+            </el-button>
+            <el-button size="default" @click="resetQuery(queryRef)">
+              <el-icon>
+                <ele-Refresh />
+              </el-icon>
+              重置
+            </el-button>
+            <el-button size="default" type="success" class="ml10" @click="onOpenAddDic">
+              <el-icon>
+                <ele-FolderAdd />
+              </el-icon>
+              新增
+            </el-button>
+            <!-- <el-button size="default" type="danger" class="ml10" @click="onRowDel(null)">
+              <el-icon>
+                <ele-Delete />
+              </el-icon>
+              删除
+            </el-button> -->
+          </el-form-item>
+        </el-form>
+      </div>
+			
+      <el-table :data="tableData.data" style="width: 100%"  row-key="id" default-expand-all :indent="16" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
+        <!-- <el-table-column type="selection" width="55" align="center" /> -->
+        <!-- <el-table-column label="ID" align="center" prop="id" width="60" /> -->
+	    	<el-table-column label="换热站" prop="name" :show-overflow-tooltip="true" />
+	    	<el-table-column label="换热站编号" prop="code" :show-overflow-tooltip="true" />
+	    	<el-table-column label="位置" prop="position" :show-overflow-tooltip="true" />
+	    	<el-table-column label="创建时间" prop="createdAt" :show-overflow-tooltip="true" />
+        <el-table-column label="操作" width="200" align="center">
+          <template #default="scope">
+			 			<el-button size="small" text type="primary" @click="onOpenDetail(scope.row)">详情</el-button>
+            <el-button size="small" text type="warning" @click="onOpenEditDic(scope.row)">修改</el-button>
+            <el-button size="small" text type="danger" @click="onRowDel(scope.row)">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination v-show="tableData.total>0" :total="tableData.total" v-model:page="tableData.param.pageNum" v-model:limit="tableData.param.pageSize" @pagination="queryList" />
+    </el-card>
+    <EditDic ref="editDicRef" :treeData="tableData.data" @queryList="queryList" />
+    <Detail ref="detailRef"  />
+  </div>
+</template>
+
+<script lang="ts">
+import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue';
+import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
+import EditDic from './component/edit.vue';
+import Detail from './component/detail.vue';
+import api from '/@/api/heatStation';
+
+// 定义接口来定义对象的类型
+interface TableDataRow {
+	id: number;
+	name: string;
+	code: string;
+	stationId: string;
+	loopTypes: number;
+	energyTypes: number;
+	heatingObject: number;
+	heatingTypes: number;
+	heatingArea: string;
+	forRealArea: string;
+	decade: string;
+	status: number;
+}
+interface TableDataState {
+	ids: number[];
+	tableData: {
+		data: Array<TableDataRow>;
+		loading: boolean;
+		param: {
+			name: string;
+			code: string;
+			status: number;
+		};
+	};
+}
+
+export default defineComponent({
+	name: 'heatStation',
+	components: { EditDic,Detail },
+	setup() {
+		const addDicRef = ref();
+		const editDicRef = ref();
+		const detailRef = ref();
+		const queryRef = ref();
+		const state = reactive<TableDataState>({
+			ids: [],
+			tableData: {
+				data: [],
+				loading: false,
+				param: {
+					name: '',
+					code: '',
+					status: -1
+				},
+			},
+		});
+		// 初始化表格数据
+		const initTableData = () => {
+			queryList();
+		};
+		const queryList = () => {
+			api.heatStation.getList(state.tableData.param)
+				.then((res: any) => {
+					state.tableData.data = res || [];
+				});
+		};
+
+		//查看详情
+		const onOpenDetail=(row: TableDataRow)=>{
+			detailRef.value.openDialog(row);
+		}
+		// 打开新增产品弹窗
+		const onOpenAddDic = () => {
+			editDicRef.value.openDialog(null, state.tableData.data);
+		};
+		// 打开修改产品弹窗
+		const onOpenEditDic = (row: TableDataRow) => {
+			editDicRef.value.openDialog(row, state.tableData.data);
+		};
+		// 删除产品
+		const onRowDel = (row: TableDataRow) => {
+			let msg = '你确定要删除所选数据?';
+			let ids: number[] = [];
+			if (row) {
+				msg = `此操作将永久删除设备:“${row.name}”,是否继续?`;
+				ids = [row.id];
+			} else {
+				ids = state.ids;
+			}
+			if (ids.length === 0) {
+				ElMessage.error('请选择要删除的数据。');
+				return;
+			}
+			ElMessageBox.confirm(msg, '提示', {
+				confirmButtonText: '确认',
+				cancelButtonText: '取消',
+				type: 'warning',
+			})
+				.then(() => {
+					// api.loop.del(ids).then(() => {
+					// 	ElMessage.success('删除成功');
+					// 	queryList();
+					// });
+				})
+				.catch(() => {});
+		};
+		// 页面加载时
+		onMounted(() => {
+			initTableData();
+		});
+		/** 重置按钮操作 */
+		const resetQuery = (formEl: FormInstance | undefined) => {
+			if (!formEl) return;
+			formEl.resetFields();
+			queryList();
+		};
+		// 多选框选中数据
+		const handleSelectionChange = (selection: TableDataRow[]) => {
+			state.ids = selection.map((item) => item.id);
+		};
+		return {
+			addDicRef,
+			editDicRef,
+			detailRef,
+			queryRef,
+			onOpenDetail,
+			onOpenAddDic,
+			onOpenEditDic,
+			onRowDel,
+			queryList,
+			resetQuery,
+			handleSelectionChange,
+			...toRefs(state),
+		};
+	},
+});
+</script>

+ 165 - 0
src/views/heatStation/loop/component/detail.vue

@@ -0,0 +1,165 @@
+<template>
+	<div class="system-edit-dic-container">
+		<el-dialog title="查看设备" v-model="isShowDialog" width="769px">
+			<el-form :model="ruleForm" ref="formRef" :rules="rules" size="default" label-width="110px">
+       <el-form-item label="设备标识" prop="key">
+          {{ruleForm.key}}
+        </el-form-item>
+        <el-form-item label="设备名称" prop="name">
+          {{ruleForm.name}}
+        </el-form-item>
+
+        
+
+           <el-form-item label="所属产品" prop="productId">
+       
+                {{ruleForm.productName}}
+            </el-form-item> 
+
+         <el-form-item label="所属部门" prop="deptId">
+               {{ruleForm.deptName}}
+            </el-form-item> 
+
+           
+        
+        <el-form-item label="设备证书" prop="certificate">
+            {{ruleForm.certificate}}
+        </el-form-item>
+
+        <el-form-item label="设备秘钥" prop="secureKey">
+            {{ruleForm.secureKey}}
+        </el-form-item>
+
+         <el-form-item label="固件版本号" prop="version">
+          {{ruleForm.version}}
+        </el-form-item>
+      
+  
+        <el-form-item label="备注" prop="desc">
+           {{ruleForm.desc}}
+        </el-form-item>
+			</el-form>
+
+		</el-dialog>
+	</div>
+</template>
+
+<script lang="ts">
+import { reactive, toRefs, defineComponent,ref, unref } from 'vue';
+import api from '/@/api/device';
+import {ElMessage} from "element-plus";
+interface RuleFormState {
+  id:number;
+  name:string;
+  certificate:string;
+  secureKey:string;
+  version:string;
+  productId:number;
+  deptId:number;
+  desc:string;
+}
+interface DicState {
+	isShowDialog: boolean;
+	ruleForm: RuleFormState;
+  rules:{}
+}
+
+export default defineComponent({
+	name: 'deviceEditPro',
+	setup(prop,{emit}) {
+    const formRef = ref<HTMLElement | null>(null);
+		const state = reactive<DicState>({
+			isShowDialog: false,
+      productData: [], // 分类数据
+      deptData: [], // 
+			ruleForm: {
+        id:0,
+        name:'',
+        productId:'',
+        deptId:0,
+        certificate:'',
+        secureKey:'',
+        version:'',
+        desc:''
+			},
+      rules: {
+       
+      }
+		});
+		// 打开弹窗
+		const openDialog = (row: RuleFormState|null) => {
+      resetForm();
+
+        api.product.getLists({ status: 1 }).then((res: any) => {
+          state.productData = res.product || [];
+        });
+        api.dept.getList({ status: -1 }).then((res: any) => {
+          state.deptData = res || [];
+        });
+
+
+      if (row){
+        // api.dict.getType(row.id).then((res:any)=>{
+        //   state.ruleForm = res.data.dictType
+        // })
+        state.ruleForm = row;
+      }
+			state.isShowDialog = true;
+		};
+    const resetForm = ()=>{
+      state.ruleForm = {
+        id:0,
+        name:'',
+        productId:'',
+        deptId:0,
+        certificate:'',
+        secureKey:'',
+        version:'',
+        desc:''
+      }
+    };
+		// 关闭弹窗
+		const closeDialog = () => {
+			state.isShowDialog = false;
+		};
+		// 取消
+		const onCancel = () => {
+			closeDialog();
+		};
+		// 新增
+		const onSubmit = () => {
+      const formWrap = unref(formRef) as any;
+      if (!formWrap) return;
+      formWrap.validate((valid: boolean) => {
+        if (valid) {
+          if(state.ruleForm.id!==0){
+            //修改
+            api.instance.edit(state.ruleForm).then(()=>{
+              ElMessage.success('设备类型修改成功');
+              closeDialog(); // 关闭弹窗
+              emit('typeList')
+            })
+          }else{
+            //添加
+            api.instance.add(state.ruleForm).then(()=>{
+              ElMessage.success('设备类型添加成功');
+              closeDialog(); // 关闭弹窗
+              emit('typeList')
+            })
+          }
+        }
+      });
+		};
+
+
+		return {
+			openDialog,
+			closeDialog,
+			onCancel,
+			onSubmit,
+      formRef,
+			...toRefs(state),
+		};
+	},
+});
+</script>

+ 200 - 0
src/views/heatStation/loop/component/edit.vue

@@ -0,0 +1,200 @@
+<template>
+	<div class="system-edit-dic-container">
+		<el-dialog :title="(ruleForm.id !== 0 ? '修改' : '添加') + '环路'" v-model="dialogVisible" width="769px">
+			<el-form :model="ruleForm" ref="formRef" :rules="rules" size="default" label-width="110px">
+				<el-form-item label="环路名称" prop="name">
+					<el-input v-model="ruleForm.name" placeholder="请输入环路名称" />
+				</el-form-item>
+				<el-form-item label="环路编号" prop="code">
+					<el-input v-model="ruleForm.code" placeholder="请输入环路编号" />
+				</el-form-item>
+				<el-form-item label="所属换热站" prop="stationId">
+					<el-input v-model="ruleForm.stationId" placeholder="请输入所属换热站" />
+				</el-form-item>
+        <el-form-item label="环路类型" prop="loopTypes">
+          <el-select v-model="ruleForm.loopTypes" placeholder="请选择环路类型" clearable size="default" style="width: 100%">
+            <el-option label="一网" :value="1" />
+            <el-option label="二网" :value="2" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="节能类型" prop="energyTypes">
+          <el-select v-model="ruleForm.energyTypes" placeholder="请选择节能类型" clearable size="default" style="width: 100%">
+            <el-option label="节能" :value="1" />
+          </el-select>
+        </el-form-item>
+        <el-row :gutter="10">
+          <el-col :span="12">
+            <el-form-item label="供暖对象" prop="heatingObject">
+              <el-select v-model="ruleForm.heatingObject" placeholder="请选择供暖对象" clearable size="default" style="width: 100%">
+                <el-option label="公建" :value="1" />
+                <el-option label="居民" :value="2" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="供暖类型" prop="heatingTypes">
+              <el-select v-model="ruleForm.heatingTypes" placeholder="请选择供暖类型" clearable size="default" style="width: 100%">
+                <el-option label="地暖" :value="1" />
+                <el-option label="暖气片" :value="2" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="10">
+          <el-col :span="12">
+            <el-form-item label="供暖面积" prop="heatingArea">
+					    <el-input v-model="ruleForm.heatingArea" placeholder="请输入供暖面积" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="实际面积" prop="forRealArea">
+					    <el-input v-model="ruleForm.forRealArea" placeholder="请输入实际面积" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="环路年代" prop="decade">
+          <el-input v-model="ruleForm.name" placeholder="请输入环路年代" />
+        </el-form-item>
+        <el-form-item label="编辑路线信息" prop="decade">
+          <baidu-map class="map" :center="{ lng: 116.404, lat: 39.915 }" :zoom="15" style="width: 100%; height: 300px">
+            <bm-navigation anchor="BMAP_ANCHOR_TOP_RIGHT"></bm-navigation>
+          </baidu-map>
+        </el-form-item>
+				<el-form-item label="状态" prop="status">
+					<el-radio v-model="ruleForm.status" :label="1">在线</el-radio>
+					<el-radio v-model="ruleForm.status" :label="0">不在线</el-radio>
+				</el-form-item>
+			</el-form>
+			<template #footer>
+				<span class="dialog-footer">
+					<el-button @click="onCancel" size="default">取 消</el-button>
+					<el-button type="primary" @click="onSubmit" size="default">{{ ruleForm.id !== 0 ? '修 改' : '添 加' }}</el-button>
+				</span>
+			</template>
+		</el-dialog>
+	</div>
+</template>
+
+<script lang="ts">
+import { reactive, toRefs, defineComponent, ref, unref } from 'vue';
+import api from '/@/api/heatStation';
+import { ElMessage } from 'element-plus';
+interface RuleFormState {
+	id: number;
+	name: string;
+	code: string;
+	stationId: string;
+	loopTypes: string;
+	energyTypes: string;
+	heatingObject: string;
+	heatingTypes: string;
+	heatingArea: string;
+	forRealArea: string;
+	decade: string;
+	status: number;
+}
+
+export default defineComponent({
+	name: 'headStationLoop',
+	setup(prop, { emit }) {
+		const formRef = ref<HTMLElement | null>(null);
+		const state = reactive({
+			dialogVisible: false,
+			ruleForm: {
+				id: 0,
+				name: '',
+        code: '',
+        stationId: '',
+        loopTypes: '',
+        energyTypes: '',
+        heatingObject: '',
+        heatingTypes: '',
+        heatingArea: '',
+        forRealArea: '',
+        decade: '',
+        status: 1
+			},
+			rules: {
+				name: [{ required: true, message: '环路名称不能为空', trigger: 'blur' }],
+				code: [{ required: true, message: '环路编号不能为空', trigger: 'blur' }],
+				stationId: [{ required: true, message: '所属换热站不能为空', trigger: 'blur' }],
+				loopTypes: [{ required: true, message: '环路类型不能为空', trigger: 'blur' }],
+				status: [{ required: true, message: '状态不能为空', trigger: 'blur' }]
+			}
+		})
+		// 打开弹窗
+		const openDialog = (row: RuleFormState | null) => {
+			resetForm()
+
+			// api.product.getLists({ status: 1 }).then((res: any) => {
+			// 	state.productData = res.product || [];
+			// });
+			// api.dept.getList({ status: -1 }).then((res: any) => {
+			// 	state.deptData = res || [];
+			// });
+
+			if (row) {
+				state.ruleForm = row
+			}
+			state.dialogVisible = true
+		}
+		const resetForm = () => {
+			state.ruleForm = {
+				id: 0,
+				name: '',
+        code: '',
+        stationId: '',
+        loopTypes: '',
+        energyTypes: '',
+        heatingObject: '',
+        heatingTypes: '',
+        heatingArea: '',
+        forRealArea: '',
+        decade: '',
+        status: 1
+			}
+		}
+		// 关闭弹窗
+		const closeDialog = () => {
+			state.dialogVisible = false
+		}
+		// 取消
+		const onCancel = () => {
+			closeDialog()
+		}
+		// 新增
+		const onSubmit = () => {
+			const formWrap = unref(formRef) as any
+			if (!formWrap) return;
+			formWrap.validate((valid: boolean) => {
+				if (valid) {
+					if (state.ruleForm.id) {
+						//修改
+						api.loop.edit(state.ruleForm).then(() => {
+							ElMessage.success('环路修改成功')
+							closeDialog() // 关闭弹窗
+							emit('querylist')
+						})
+					} else {
+						//添加
+						api.loop.add(state.ruleForm).then(() => {
+							ElMessage.success('环路添加成功')
+							closeDialog() // 关闭弹窗
+							emit('querylist')
+						})
+					}
+				}
+			})
+		}
+
+		return {
+			openDialog,
+			closeDialog,
+			onCancel,
+			onSubmit,
+			formRef,
+			...toRefs(state)
+		}
+	}
+})
+</script>

+ 249 - 0
src/views/heatStation/loop/index.vue

@@ -0,0 +1,249 @@
+<template>
+  <div class="system-dic-container">
+    <el-card shadow="hover">
+      <div class="system-user-search mb15">
+        <el-form :model="tableData.param" ref="queryRef" :inline="true" label-width="68px">
+          <el-form-item label="环路名称" prop="name">
+            <el-input v-model="tableData.param.name" placeholder="请输入环路名称" clearable size="default" style="width: 240px" @keyup.enter="queryList" />
+          </el-form-item>
+		  		<el-form-item label="环路编号" prop="code">
+            <el-input v-model="tableData.param.code" placeholder="请输入环路编号" clearable size="default" style="width: 240px" @keyup.enter="queryList" />
+          </el-form-item>
+          <el-form-item label="环路类型" prop="loopTypes" style="width: 200px;">
+            <el-select v-model="tableData.param.loopTypes" placeholder="全部" clearable size="default" style="width: 240px">
+              <el-option label="一网" :value="1" />
+              <el-option label="二网" :value="2" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="供暖对象" prop="heatingObject" style="width: 200px;">
+            <el-select v-model="tableData.param.heatingObject" placeholder="全部" clearable size="default" style="width: 240px">
+              <el-option label="公建" :value="1" />
+              <el-option label="居民" :value="2" />
+            </el-select>
+          </el-form-item>
+          <el-form-item>
+            <el-button size="default" type="primary" class="ml10" @click="queryList">
+              <el-icon>
+                <ele-Search />
+              </el-icon>
+              查询
+            </el-button>
+            <el-button size="default" @click="resetQuery(queryRef)">
+              <el-icon>
+                <ele-Refresh />
+              </el-icon>
+              重置
+            </el-button>
+            <el-button size="default" type="success" class="ml10" @click="onOpenAddDic">
+              <el-icon>
+                <ele-FolderAdd />
+              </el-icon>
+              新增
+            </el-button>
+            <!-- <el-button size="default" type="danger" class="ml10" @click="onRowDel(null)">
+              <el-icon>
+                <ele-Delete />
+              </el-icon>
+              删除
+            </el-button> -->
+          </el-form-item>
+        </el-form>
+      </div>
+      <el-table :data="tableData.data" style="width: 100%" @selection-change="handleSelectionChange">
+        <!-- <el-table-column type="selection" width="55" align="center" /> -->
+        <el-table-column label="ID" align="center" prop="id" width="60" />
+	    	<el-table-column label="环路名称" prop="name" :show-overflow-tooltip="true" />
+	    	<el-table-column label="环路编号" prop="code" :show-overflow-tooltip="true" />
+	    	<el-table-column label="所属换热站" prop="stationId" :show-overflow-tooltip="true" />
+	    	<el-table-column label="环路类型" prop="loopTypes">
+          <template #default="scope">
+            <el-tag type="success" size="small" v-if="scope.row.loopTypes === 1">一网</el-tag>
+            <el-tag type="info" size="small" v-else-if="scope.row.loopTypes === 2">二网</el-tag>
+          </template>
+        </el-table-column>
+	    	<el-table-column label="节能类型" prop="energyTypes">
+          <template #default="scope">
+            <el-tag type="success" size="small" v-if="scope.row.energyTypes === 1">节能</el-tag>
+          </template>
+        </el-table-column>
+	    	<el-table-column label="供暖对象" prop="heatingObject" :show-overflow-tooltip="true">
+          <template #default="scope">
+            <el-tag type="success" size="small" v-if="scope.row.heatingObject === 1">公建</el-tag>
+            <el-tag type="info" size="small" v-else-if="scope.row.heatingObject === 2">居民</el-tag>
+          </template>
+        </el-table-column>
+	    	<el-table-column label="供暖类型" prop="heatingTypes">
+          <template #default="scope">
+            <el-tag type="success" size="small" v-if="scope.row.heatingTypes === 1">地暖</el-tag>
+            <el-tag type="info" size="small" v-else-if="scope.row.heatingTypes === 2">暖气片</el-tag>
+          </template>
+        </el-table-column>
+	    	<el-table-column label="供暖面积" prop="heatingArea" :show-overflow-tooltip="true" />
+	    	<el-table-column label="实际面积" prop="forRealArea" :show-overflow-tooltip="true" />
+	    	<el-table-column label="环路年代" prop="decade" :show-overflow-tooltip="true" />
+        <el-table-column prop="status" label="状态" align="center">
+          <template #default="scope">
+            <el-tag type="success" size="small" v-if="scope.row.status === 0">不在线</el-tag>
+            <el-tag type="info" size="small" v-else-if="scope.row.status === 1">在线</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="操作" width="200" align="center">
+          <template #default="scope">
+			 			<el-button size="small" text type="primary" @click="onOpenDetail(scope.row)">详情</el-button>
+            <el-button size="small" text type="warning" @click="onOpenEditDic(scope.row)">修改</el-button>
+            <el-button size="small" text type="danger" @click="onRowDel(scope.row)">删除</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination v-show="tableData.total>0" :total="tableData.total" v-model:page="tableData.param.pageNum" v-model:limit="tableData.param.pageSize" @pagination="queryList" />
+    </el-card>
+    <EditDic ref="editDicRef" @queryList="queryList" />
+    <Detail ref="detailRef"  />
+  </div>
+</template>
+
+<script lang="ts">
+import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue';
+import { ElMessageBox, ElMessage, FormInstance } from 'element-plus';
+import EditDic from './component/edit.vue';
+import Detail from './component/detail.vue';
+import api from '/@/api/heatStation';
+
+// 定义接口来定义对象的类型
+interface TableDataRow {
+	id: number;
+	name: string;
+	code: string;
+	stationId: string;
+	loopTypes: number;
+	energyTypes: number;
+	heatingObject: number;
+	heatingTypes: number;
+	heatingArea: string;
+	forRealArea: string;
+	decade: string;
+	status: number;
+}
+interface TableDataState {
+	ids: number[];
+	tableData: {
+		data: Array<TableDataRow>;
+		total: number;
+		loading: boolean;
+		param: {
+			pageNum: number;
+			pageSize: number;
+			name: string;
+			code: string;
+			loopTypes: string;
+			heatingObject: string;
+		};
+	};
+}
+
+export default defineComponent({
+	name: 'loop',
+	components: { EditDic,Detail },
+	setup() {
+		const addDicRef = ref();
+		const editDicRef = ref();
+		const detailRef=ref();
+		const queryRef = ref();
+		const state = reactive<TableDataState>({
+			ids: [],
+			tableData: {
+				data: [],
+				total: 0,
+				loading: false,
+				param: {
+					pageNum: 1,
+					pageSize: 10,
+					name: '',
+					code: '',
+					loopTypes: '',
+					heatingObject: ''
+				},
+			},
+		});
+		// 初始化表格数据
+		const initTableData = () => {
+			queryList();
+		};
+		const queryList = () => {
+			api.loop.getList(state.tableData.param).then((res: any) => {
+				console.log(res);
+				state.tableData.data = res.Data || [];
+				state.tableData.total = res.Total;
+			});
+		};
+
+		//查看详情
+		const onOpenDetail=(row: TableDataRow)=>{
+			detailRef.value.openDialog(row);
+		}
+		// 打开新增产品弹窗
+		const onOpenAddDic = () => {
+			editDicRef.value.openDialog();
+		};
+		// 打开修改产品弹窗
+		const onOpenEditDic = (row: TableDataRow) => {
+			editDicRef.value.openDialog(row);
+		};
+		// 删除产品
+		const onRowDel = (row: TableDataRow) => {
+			let msg = '你确定要删除所选数据?';
+			let ids: number[] = [];
+			if (row) {
+				msg = `此操作将永久删除设备:“${row.name}”,是否继续?`;
+				ids = [row.id];
+			} else {
+				ids = state.ids;
+			}
+			if (ids.length === 0) {
+				ElMessage.error('请选择要删除的数据。');
+				return;
+			}
+			ElMessageBox.confirm(msg, '提示', {
+				confirmButtonText: '确认',
+				cancelButtonText: '取消',
+				type: 'warning',
+			})
+				.then(() => {
+					// api.loop.del(ids).then(() => {
+					// 	ElMessage.success('删除成功');
+					// 	queryList();
+					// });
+				})
+				.catch(() => {});
+		};
+		// 页面加载时
+		onMounted(() => {
+			initTableData();
+		});
+		/** 重置按钮操作 */
+		const resetQuery = (formEl: FormInstance | undefined) => {
+			if (!formEl) return;
+			formEl.resetFields();
+			queryList();
+		};
+		// 多选框选中数据
+		const handleSelectionChange = (selection: TableDataRow[]) => {
+			state.ids = selection.map((item) => item.id);
+		};
+		return {
+			addDicRef,
+			editDicRef,
+			detailRef,
+			queryRef,
+			onOpenDetail,
+			onOpenAddDic,
+			onOpenEditDic,
+			onRowDel,
+			queryList,
+			resetQuery,
+			handleSelectionChange,
+			...toRefs(state),
+		};
+	},
+});
+</script>