Эх сурвалжийг харах

供热站管理 小区、楼宇

picasso 3 жил өмнө
parent
commit
67f9863932

+ 3 - 0
src/api/heatingDistrict/index.ts

@@ -1,6 +1,9 @@
 import { get, post, del, put } from '/@/utils/request';
 
 export default {
+  heatingDistrict: {
+    getTree: (params: object) => get('/region/zhgy/tree', params),
+  },
   regionalManage: {
     allList: (params: object) => get('/region/plot/all', params),
     getList: (params: object) => get('/region/plot/list', params),

+ 200 - 0
src/views/heatingDistrict/heatingDistrictManage/children/floor/component/detail.vue

@@ -0,0 +1,200 @@
+<template>
+	<div class="system-edit-dic-container">
+		<el-dialog :title="'环路详情'" v-model="dialogVisible" width="950px">
+			<el-form :model="ruleForm" ref="formRef" size="default" label-width="110px">
+				<el-form-item label="环路名称" prop="name">
+					{{ ruleForm.name }}
+				</el-form-item>
+				<el-form-item label="环路编号" prop="code">
+					{{ ruleForm.code }}
+				</el-form-item>
+				<el-form-item label="所属换热站" prop="stationId">
+          {{ ruleForm.stationId }}
+					<!-- <el-tree-select
+						v-model="ruleForm.stationId"
+						: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="loopTypes">
+          {{ ruleForm.loopTypes === 1 ? '一网' : '二网' }}
+        </el-form-item>
+        <el-form-item label="节能类型" prop="energyTypes">
+          {{ ruleForm.energyTypes === 1 ? '节能' : '' }}
+        </el-form-item>
+        <el-row :gutter="10">
+          <el-col :span="12">
+            <el-form-item label="供暖对象" prop="heatingObject">
+              {{ ruleForm.heatingObject === 1 ? '公建' : '居民' }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="供暖类型" prop="heatingTypes">
+              {{ ruleForm.heatingTypes === 1 ? '地暖' : '暖气片' }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="10">
+          <el-col :span="12">
+            <el-form-item label="供暖面积" prop="heatingArea">
+              {{ ruleForm.heatingArea }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="实际面积" prop="forRealArea">
+              {{ ruleForm.forRealArea }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="环路年代" prop="decade">
+          {{ ruleForm.decade }}
+        </el-form-item>
+				<el-form-item label="状态" prop="status">
+          {{ ruleForm.decade === 1 ? '在线' : '不在线' }}
+				</el-form-item>
+        <el-form-item label="路线信息" prop="">
+					<div class="mb10" style="width: 100%">
+						<div style="display: flex;" class="mb10" v-for="(item, index) in pointList" :key="index">
+							<el-input v-model="item.position" :disabled="!item.editFalg" @keydown="onLocalChange(item, index)" @change="onLocalChange(item, index)" placeholder="请输入关键字进行搜索" clearable style="flex: 1; margin-right: 10px"></el-input>
+							<span>排序:</span>
+							<el-input-number v-model="item.sort" :controls="false" :disabled="!item.editFalg" placeholder="排序" clearable style="width: 100px; margin-right: 10px"></el-input-number>
+						</div>
+					</div>
+        </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 } from 'vue';
+import api from '/@/api/heatStation';
+import { ElMessage } from 'element-plus';
+interface Point {
+	sort?: number;
+	lnt: number;
+	lat: number
+}
+interface RuleFormState {
+	id?: number;
+	name: string;
+	code: string;
+	stationId: string;
+	loopTypes: string;
+	energyTypes: string;
+	heatingObject: string;
+	heatingTypes: string;
+	heatingArea: string;
+	forRealArea: string;
+	viaPoint: Array<Point>;
+	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: '',
+				viaPoint: [],
+        status: 1
+			},
+			treeData: [],
+      pointList: [] as any
+		})
+		// 打开弹窗
+		const openDialog = (row: RuleFormState | null) => {
+			resetForm()
+			queryTree()
+			if (row) {
+				(state.ruleForm as any).id = row.id
+				getDetail()
+			}
+			state.dialogVisible = true
+		}
+		const resetForm = () => {
+			state.ruleForm = {
+				id: 0,
+				name: '',
+        code: '',
+        stationId: '',
+        loopTypes: '',
+        energyTypes: '',
+        heatingObject: '',
+        heatingTypes: '',
+        heatingArea: '',
+        forRealArea: '',
+				viaPoint: [],
+        decade: '',
+        status: 1
+			}
+		}
+		// 关闭弹窗
+		const closeDialog = () => {
+			state.dialogVisible = false
+		}
+		// 取消
+		const onCancel = () => {
+			closeDialog()
+			state.pointList = []
+		}
+		const queryTree = () => {
+			api.heatStation.getList({
+					name: '',
+					code: '',
+					status: -1
+				})
+				.then((res: any) => {
+					state.treeData = res || [];
+				});
+		};
+		const getDetail = () => {
+			api.loop.detail(state.ruleForm.id)
+				.then((res: any) => {
+					state.ruleForm = {
+						...res
+					}
+					state.pointList = state.ruleForm.viaPoint.map((item: any) => ({
+						...item,
+						editFlag: false
+					}))
+				})
+		}
+
+		return {
+			openDialog,
+			closeDialog,
+			onCancel,
+			formRef,
+			...toRefs(state)
+		}
+	}
+})
+</script>

+ 135 - 0
src/views/heatingDistrict/heatingDistrictManage/children/floor/component/edit.vue

@@ -0,0 +1,135 @@
+<template>
+	<div class="system-edit-dic-container">
+		<el-dialog :title="(ruleForm.id !== 0 ? '修改' : '添加') + '楼宇'" v-model="dialogVisible" width="550px">
+			<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="number">
+					<el-input v-model="ruleForm.number" 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>
+			<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/heatingDistrict';
+import heatApi from '/@/api/heatStation';
+import { ElMessage } from 'element-plus';
+interface RuleFormState {
+	id?: number;
+	name: string;
+	organizationId: string;
+}
+
+export default defineComponent({
+	name: 'edit',
+	setup(prop, { emit }) {
+		const formRef = ref<HTMLElement | null>(null);
+		const state = reactive({
+			dialogVisible: false,
+			ruleForm: {
+				id: 0,
+				name: '',
+        number: '',
+				plotId: '',
+				organizationId: '',
+				status: 1
+			},
+			rules: {
+				name: [{ required: true, message: '楼宇名称不能为空', trigger: ['blur', 'change'] }],
+				number: [{ required: true, message: '楼号不能为空', trigger: ['blur', 'change'] }],
+			}
+		})
+		// 打开弹窗
+		const openDialog = (row: RuleFormState | null, params: any) => {
+			resetForm()
+			if (params) {
+				state.ruleForm = {
+					...state.ruleForm,
+					...params
+				}
+			}
+			if (row) {
+				(state.ruleForm as any).id = row.id
+				getDetail()
+			}
+			state.dialogVisible = true
+		}
+		const resetForm = () => {
+			state.ruleForm = {
+				id: 0,
+				name: '',
+        number: '',
+				plotId: '',
+				organizationId: '',
+				status: 1
+			}
+		}
+		// 关闭弹窗
+		const closeDialog = () => {
+			state.dialogVisible = false;
+			(formRef.value as any).clearValidate()
+		}
+		// 取消
+		const onCancel = () => {
+			closeDialog()
+		}
+		const getDetail = () => {
+			api.floor.detail(state.ruleForm.id)
+				.then((res: any) => {
+					state.ruleForm = {
+						...res
+					}
+				})
+		}
+		// 新增
+		const onSubmit = () => {
+			const formWrap = unref(formRef) as any
+			if (!formWrap) return;
+			formWrap.validate((valid: boolean) => {
+				if (valid) {
+					let params = { ...state.ruleForm }
+
+					if (params.id) {
+						//修改
+						api.floor.edit(params).then(() => {
+							ElMessage.success('楼宇修改成功')
+							closeDialog() // 关闭弹窗
+							emit('queryList')
+						})
+					} else {
+						//添加
+						api.floor.add(params).then(() => {
+							ElMessage.success('楼宇添加成功')
+							closeDialog() // 关闭弹窗
+							emit('queryList')
+						})
+					}
+				}
+			})
+		}
+
+		return {
+			openDialog,
+			closeDialog,
+			onCancel,
+			onSubmit,
+			formRef,
+			...toRefs(state)
+		}
+	}
+})
+</script>

+ 195 - 0
src/views/heatingDistrict/heatingDistrictManage/children/floor/index.vue

@@ -0,0 +1,195 @@
+<template>
+  <div class="system-dic-container">
+    <div>
+      <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="number">
+            <el-input v-model="tableData.param.number" placeholder="请输入楼号" clearable size="default" style="width: 240px" @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="onOpenDialog()">
+              <el-icon>
+                <ele-FolderAdd />
+              </el-icon>
+              新增
+            </el-button>
+          </el-form-item>
+        </el-form>
+      </div>
+      <el-table :data="tableData.data" v-loading="tableData.loading" style="width: 100%" >
+        <!-- <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" min-width="100" />
+	    	<el-table-column label="楼号" prop="number" min-width="100" />
+	    	<!-- <el-table-column label="单元数" prop="name" /> -->
+        <el-table-column label="小区名称" prop="" min-width="100">
+          <template #default="{ row }">
+            {{ row.ZhgyPlotInfo ? row.ZhgyPlotInfo.name : '-' }}
+          </template>
+        </el-table-column>
+        <el-table-column label="组织名称" prop="" min-width="100">
+          <template #default="{ row }">
+            {{ row.SysOrganization ? row.SysOrganization.name : '-' }}
+          </template>
+        </el-table-column>
+	    	<el-table-column label="更新时间" prop="createdAt" width="180" />
+				<el-table-column prop="status" label="启用状态" width="120" align="center">
+					<template #default="scope">
+						<el-switch v-model="scope.row.status" inline-prompt :active-value="1" :inactive-value="0" active-text="启" inactive-text="禁" @change="handleStatusChange(scope.row)">
+						</el-switch>
+					</template>
+				</el-table-column>
+        <el-table-column label="操作" width="200" align="center" fixed="right">
+          <template #default="scope">
+            <el-button size="small" text type="warning" @click="onOpenDialog(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" />
+    </div>
+    <EditDic ref="editDicRef" @queryList="queryList" />
+    <Detail ref="detailRef"  />
+  </div>
+</template>
+
+<script lang="ts">
+import { toRefs, reactive, onMounted, ref, defineComponent, watch } 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/heatingDistrict';
+
+export default defineComponent({
+	name: 'loop',
+	components: { EditDic,Detail },
+	props: {
+		organizationId: {
+			default: ''
+		},
+		plotId: {
+			default: ''
+		}
+	},
+	setup(prop) {
+		const editDicRef = ref();
+		const detailRef=ref();
+		const queryRef = ref();
+		const state = reactive({
+			ids: [],
+			tableData: {
+				data: [],
+				total: 0,
+				loading: false,
+				param: {
+					pageNum: 1,
+					pageSize: 10,
+					name: '',
+					number: '',
+					plotId: '',
+					organizationId: '',
+					status: -1
+				},
+			},
+		});
+
+		const queryList = () => {
+			state.tableData.loading = true
+			api.floor.getList(state.tableData.param).then((res: any) => {
+				state.tableData.data = res.Info || [];
+				state.tableData.total = res.Total;
+				state.tableData.loading = false
+			});
+		};
+		
+		watch(() => prop.plotId, () => {
+			state.tableData.param.organizationId = prop.organizationId
+			state.tableData.param.plotId = prop.plotId
+			queryList()
+		}, {
+			deep: true,
+			immediate: true
+		})
+
+		//查看详情
+		const onOpenDetail=(row: any)=>{
+			detailRef.value.openDialog(row);
+		}
+		// 打开新增修改弹窗
+		const onOpenDialog = (row: any) => {
+			editDicRef.value.openDialog(row, { organizationId: prop.organizationId, plotId: prop.plotId });
+		};
+		
+		// 状态修改
+		const handleStatusChange = (row: any) => {
+			let text = row.status === 1 ? '启用' : '停用';
+			ElMessageBox.confirm('确认要"' + text + '":"' + row.name + '"楼宇吗?', '警告', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				type: 'warning',
+			})
+				.then(function () {
+					return api.floor.setStatus(row.id, row.status);
+				})
+				.then(() => {
+					ElMessage.success(text + '成功');
+				})
+				.catch(function () {
+					row.status = row.status === 0 ? 1 : 0;
+				});
+		};
+		// 删除产品
+		const onRowDel = (row: any) => {
+			let msg = `此操作将永久删除楼宇:“${row.name}”,是否继续?`;
+
+			ElMessageBox.confirm(msg, '提示', {
+				confirmButtonText: '确认',
+				cancelButtonText: '取消',
+				type: 'warning',
+			})
+				.then(() => {
+					api.floor.del(row.id).then(() => {
+						ElMessage.success('删除成功');
+						queryList();
+					});
+				})
+				.catch(() => {});
+		};
+
+		/** 重置按钮操作 */
+		const resetQuery = (formEl: FormInstance | undefined) => {
+			if (!formEl) return;
+			formEl.resetFields();
+			queryList();
+		};
+
+		return {
+			editDicRef,
+			detailRef,
+			queryRef,
+			onOpenDetail,
+			onOpenDialog,
+			onRowDel,
+			queryList,
+			resetQuery,
+			handleStatusChange,
+			...toRefs(state),
+		};
+	},
+});
+</script>

+ 200 - 0
src/views/heatingDistrict/heatingDistrictManage/children/regional/component/detail.vue

@@ -0,0 +1,200 @@
+<template>
+	<div class="system-edit-dic-container">
+		<el-dialog :title="'环路详情'" v-model="dialogVisible" width="950px">
+			<el-form :model="ruleForm" ref="formRef" size="default" label-width="110px">
+				<el-form-item label="环路名称" prop="name">
+					{{ ruleForm.name }}
+				</el-form-item>
+				<el-form-item label="环路编号" prop="code">
+					{{ ruleForm.code }}
+				</el-form-item>
+				<el-form-item label="所属换热站" prop="stationId">
+          {{ ruleForm.stationId }}
+					<!-- <el-tree-select
+						v-model="ruleForm.stationId"
+						: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="loopTypes">
+          {{ ruleForm.loopTypes === 1 ? '一网' : '二网' }}
+        </el-form-item>
+        <el-form-item label="节能类型" prop="energyTypes">
+          {{ ruleForm.energyTypes === 1 ? '节能' : '' }}
+        </el-form-item>
+        <el-row :gutter="10">
+          <el-col :span="12">
+            <el-form-item label="供暖对象" prop="heatingObject">
+              {{ ruleForm.heatingObject === 1 ? '公建' : '居民' }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="供暖类型" prop="heatingTypes">
+              {{ ruleForm.heatingTypes === 1 ? '地暖' : '暖气片' }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="10">
+          <el-col :span="12">
+            <el-form-item label="供暖面积" prop="heatingArea">
+              {{ ruleForm.heatingArea }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="实际面积" prop="forRealArea">
+              {{ ruleForm.forRealArea }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="环路年代" prop="decade">
+          {{ ruleForm.decade }}
+        </el-form-item>
+				<el-form-item label="状态" prop="status">
+          {{ ruleForm.decade === 1 ? '在线' : '不在线' }}
+				</el-form-item>
+        <el-form-item label="路线信息" prop="">
+					<div class="mb10" style="width: 100%">
+						<div style="display: flex;" class="mb10" v-for="(item, index) in pointList" :key="index">
+							<el-input v-model="item.position" :disabled="!item.editFalg" @keydown="onLocalChange(item, index)" @change="onLocalChange(item, index)" placeholder="请输入关键字进行搜索" clearable style="flex: 1; margin-right: 10px"></el-input>
+							<span>排序:</span>
+							<el-input-number v-model="item.sort" :controls="false" :disabled="!item.editFalg" placeholder="排序" clearable style="width: 100px; margin-right: 10px"></el-input-number>
+						</div>
+					</div>
+        </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 } from 'vue';
+import api from '/@/api/heatStation';
+import { ElMessage } from 'element-plus';
+interface Point {
+	sort?: number;
+	lnt: number;
+	lat: number
+}
+interface RuleFormState {
+	id?: number;
+	name: string;
+	code: string;
+	stationId: string;
+	loopTypes: string;
+	energyTypes: string;
+	heatingObject: string;
+	heatingTypes: string;
+	heatingArea: string;
+	forRealArea: string;
+	viaPoint: Array<Point>;
+	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: '',
+				viaPoint: [],
+        status: 1
+			},
+			treeData: [],
+      pointList: [] as any
+		})
+		// 打开弹窗
+		const openDialog = (row: RuleFormState | null) => {
+			resetForm()
+			queryTree()
+			if (row) {
+				(state.ruleForm as any).id = row.id
+				getDetail()
+			}
+			state.dialogVisible = true
+		}
+		const resetForm = () => {
+			state.ruleForm = {
+				id: 0,
+				name: '',
+        code: '',
+        stationId: '',
+        loopTypes: '',
+        energyTypes: '',
+        heatingObject: '',
+        heatingTypes: '',
+        heatingArea: '',
+        forRealArea: '',
+				viaPoint: [],
+        decade: '',
+        status: 1
+			}
+		}
+		// 关闭弹窗
+		const closeDialog = () => {
+			state.dialogVisible = false
+		}
+		// 取消
+		const onCancel = () => {
+			closeDialog()
+			state.pointList = []
+		}
+		const queryTree = () => {
+			api.heatStation.getList({
+					name: '',
+					code: '',
+					status: -1
+				})
+				.then((res: any) => {
+					state.treeData = res || [];
+				});
+		};
+		const getDetail = () => {
+			api.loop.detail(state.ruleForm.id)
+				.then((res: any) => {
+					state.ruleForm = {
+						...res
+					}
+					state.pointList = state.ruleForm.viaPoint.map((item: any) => ({
+						...item,
+						editFlag: false
+					}))
+				})
+		}
+
+		return {
+			openDialog,
+			closeDialog,
+			onCancel,
+			formRef,
+			...toRefs(state)
+		}
+	}
+})
+</script>

+ 153 - 0
src/views/heatingDistrict/heatingDistrictManage/children/regional/component/edit.vue

@@ -0,0 +1,153 @@
+<template>
+	<div class="system-edit-dic-container">
+		<el-dialog :title="(ruleForm.id !== 0 ? '修改' : '添加') + '小区'" v-model="dialogVisible" width="550px">
+			<el-form :model="ruleForm" ref="formRef" :rules="rules" size="default" label-width="110px">
+				<!-- <el-form-item label="所属组织" prop="organizationId">
+					<el-tree-select
+						v-model="ruleForm.organizationId"
+						:data="orgList"
+						: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="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, nextTick } from 'vue';
+import api from '/@/api/heatingDistrict';
+import heatApi from '/@/api/heatStation';
+import { ElMessage } from 'element-plus';
+interface RuleFormState {
+	id?: number;
+	name: string;
+	organizationId: string;
+}
+
+export default defineComponent({
+	name: 'edit',
+	setup(prop, { emit }) {
+		const formRef = ref<HTMLElement | null>(null);
+		const state = reactive({
+			dialogVisible: false,
+			ruleForm: {
+				id: 0,
+				name: '',
+        organizationId: '',
+				status: 1
+			},
+			rules: {
+				name: [{ required: true, message: '小区名称不能为空', trigger: ['blur', 'change'] }],
+				organizationId: [{ required: true, message: '所属组织不能为空', trigger: ['blur', 'change'] }]
+			},
+			orgList: [],
+			heatList: []
+		})
+		// 打开弹窗
+		const openDialog = (row: RuleFormState | null, organizationId: any) => {
+			resetForm()
+			queryTree()
+			if (organizationId) {
+				state.ruleForm.organizationId = organizationId
+			}
+			if (row) {
+				(state.ruleForm as any).id = row.id
+				getDetail()
+			}
+			state.dialogVisible = true
+		}
+		const resetForm = () => {
+			state.ruleForm = {
+				id: 0,
+				name: '',
+        organizationId: '',
+				status: 1
+			}
+		}
+		// 关闭弹窗
+		const closeDialog = () => {
+			state.dialogVisible = false;
+			(formRef.value as any).clearValidate()
+		}
+		// 取消
+		const onCancel = () => {
+			closeDialog()
+		}
+		const queryTree = () => {
+			heatApi.heatStation.getList({
+					name: '',
+					code: '',
+					status: -1
+				})
+				.then((res: any) => {
+					state.heatList = res || [];
+				});
+		};
+		const getDetail = () => {
+			api.regionalManage.detail(state.ruleForm.id)
+				.then((res: any) => {
+					state.ruleForm = {
+						...res
+					}
+				})
+		}
+		// 新增
+		const onSubmit = () => {
+			const formWrap = unref(formRef) as any
+			if (!formWrap) return;
+			formWrap.validate((valid: boolean) => {
+				if (valid) {
+					let params = { ...state.ruleForm }
+
+					if (params.id) {
+						//修改
+						api.regionalManage.edit(params).then(() => {
+							ElMessage.success('小区修改成功')
+							closeDialog() // 关闭弹窗
+							emit('queryList')
+						})
+					} else {
+						//添加
+						api.regionalManage.add(params).then(() => {
+							ElMessage.success('小区添加成功')
+							closeDialog() // 关闭弹窗
+							emit('queryList')
+						})
+					}
+				}
+			})
+		}
+
+		return {
+			openDialog,
+			closeDialog,
+			onCancel,
+			onSubmit,
+			formRef,
+			...toRefs(state)
+		}
+	}
+})
+</script>

+ 211 - 0
src/views/heatingDistrict/heatingDistrictManage/children/regional/index.vue

@@ -0,0 +1,211 @@
+<template>
+  <div class="system-dic-container">
+    <div>
+      <div class="system-user-search mb15">
+        <el-form :model="tableData.param" ref="queryRef" :inline="true" label-width="68px">
+          <!-- <el-form-item label="所属组织" prop="organizationId">
+						<el-tree-select
+							v-model="tableData.param.organizationId"
+							:data="orgList"
+							:props="{
+								label: 'name',
+								children: 'children'
+							}"
+							placeholder="请选择"
+							node-key="id"
+							:clearable="true"
+							check-strictly
+							style="width: 100%;"
+							:render-after-expand="true"
+							size="default"
+						/>
+          </el-form-item> -->
+          <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>
+            <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" v-loading="tableData.loading" style="width: 100%" >
+        <!-- <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" min-width="100" />
+        <el-table-column label="组织名称" prop="" min-width="100">
+					<template #default="{ row }">
+						{{ row.SysOrganization.name }}
+					</template>
+				</el-table-column>
+	    	<el-table-column label="更新时间" prop="createdAt" width="180" />
+				<el-table-column prop="status" label="启用状态" width="120" align="center">
+					<template #default="scope">
+						<el-switch v-model="scope.row.status" inline-prompt :active-value="1" :inactive-value="0" active-text="启" inactive-text="禁" @change="handleStatusChange(scope.row)">
+						</el-switch>
+					</template>
+				</el-table-column>
+        <el-table-column label="操作" width="200" align="center" fixed="right">
+          <template #default="scope">
+            <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" />
+    </div>
+    <EditDic ref="editDicRef" @queryList="queryList" />
+    <Detail ref="detailRef"  />
+  </div>
+</template>
+
+<script lang="ts">
+import { toRefs, reactive, onMounted, ref, defineComponent, watch } 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/heatingDistrict';
+import systemApi from '/@/api/system';
+import { nextTick } from 'process';
+
+export default defineComponent({
+	name: 'loop',
+	components: { EditDic,Detail },
+	props: {
+		organizationId: {
+			default: ''
+		}
+	},
+	setup(prop) {
+		const addDicRef = ref();
+		const editDicRef = ref();
+		const detailRef=ref();
+		const queryRef = ref();
+		const state = reactive({
+			ids: [],
+			tableData: {
+				data: [],
+				total: 0,
+				loading: false,
+				param: {
+					pageNum: 1,
+					pageSize: 10,
+					name: '',
+					organizationId: '',
+					status: -1
+				},
+			},
+		});
+
+		const queryList = () => {
+			state.tableData.loading = true
+			api.regionalManage.getList(state.tableData.param).then((res: any) => {
+				console.log(res);
+				state.tableData.data = res.Info || [];
+				state.tableData.total = res.Total;
+				state.tableData.loading = false
+			});
+		};
+
+		watch(() => prop.organizationId, () => {
+			state.tableData.param.organizationId = prop.organizationId
+			queryList()
+		}, {
+			deep: true,
+			immediate: true
+		})
+		//查看详情
+		const onOpenDetail=(row: any)=>{
+			detailRef.value.openDialog(row);
+		}
+		// 打开新增产品弹窗
+		const onOpenAddDic = () => {
+			editDicRef.value.openDialog(null, prop.organizationId);
+		};
+		// 打开修改产品弹窗
+		const onOpenEditDic = (row: any) => {
+			editDicRef.value.openDialog(row);
+		};
+		
+		// 状态修改
+		const handleStatusChange = (row: any) => {
+			let text = row.status === 1 ? '启用' : '停用';
+			ElMessageBox.confirm('确认要"' + text + '":"' + row.name + '"小区吗?', '警告', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				type: 'warning',
+			})
+				.then(function () {
+					return api.regionalManage.setStatus(row.id, row.status);
+				})
+				.then(() => {
+					ElMessage.success(text + '成功');
+				})
+				.catch(function () {
+					row.status = row.status === 0 ? 1 : 0;
+				});
+		};
+		// 删除产品
+		const onRowDel = (row: any) => {
+			let msg = `此操作将永久删除小区:“${row.name}”,是否继续?`;
+
+			ElMessageBox.confirm(msg, '提示', {
+				confirmButtonText: '确认',
+				cancelButtonText: '取消',
+				type: 'warning',
+			})
+				.then(() => {
+					api.regionalManage.del(row.id).then(() => {
+						ElMessage.success('删除成功');
+						queryList();
+					});
+				})
+				.catch(() => {});
+		};
+
+		/** 重置按钮操作 */
+		const resetQuery = (formEl: FormInstance | undefined) => {
+			if (!formEl) return;
+			formEl.resetFields();
+			queryList();
+		};
+
+		return {
+			addDicRef,
+			editDicRef,
+			detailRef,
+			queryRef,
+			onOpenDetail,
+			onOpenAddDic,
+			onOpenEditDic,
+			onRowDel,
+			queryList,
+			resetQuery,
+			handleStatusChange,
+			...toRefs(state),
+		};
+	},
+});
+</script>

+ 200 - 0
src/views/heatingDistrict/heatingDistrictManage/children/resident/component/detail.vue

@@ -0,0 +1,200 @@
+<template>
+	<div class="system-edit-dic-container">
+		<el-dialog :title="'环路详情'" v-model="dialogVisible" width="950px">
+			<el-form :model="ruleForm" ref="formRef" size="default" label-width="110px">
+				<el-form-item label="环路名称" prop="name">
+					{{ ruleForm.name }}
+				</el-form-item>
+				<el-form-item label="环路编号" prop="code">
+					{{ ruleForm.code }}
+				</el-form-item>
+				<el-form-item label="所属换热站" prop="stationId">
+          {{ ruleForm.stationId }}
+					<!-- <el-tree-select
+						v-model="ruleForm.stationId"
+						: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="loopTypes">
+          {{ ruleForm.loopTypes === 1 ? '一网' : '二网' }}
+        </el-form-item>
+        <el-form-item label="节能类型" prop="energyTypes">
+          {{ ruleForm.energyTypes === 1 ? '节能' : '' }}
+        </el-form-item>
+        <el-row :gutter="10">
+          <el-col :span="12">
+            <el-form-item label="供暖对象" prop="heatingObject">
+              {{ ruleForm.heatingObject === 1 ? '公建' : '居民' }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="供暖类型" prop="heatingTypes">
+              {{ ruleForm.heatingTypes === 1 ? '地暖' : '暖气片' }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="10">
+          <el-col :span="12">
+            <el-form-item label="供暖面积" prop="heatingArea">
+              {{ ruleForm.heatingArea }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="实际面积" prop="forRealArea">
+              {{ ruleForm.forRealArea }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="环路年代" prop="decade">
+          {{ ruleForm.decade }}
+        </el-form-item>
+				<el-form-item label="状态" prop="status">
+          {{ ruleForm.decade === 1 ? '在线' : '不在线' }}
+				</el-form-item>
+        <el-form-item label="路线信息" prop="">
+					<div class="mb10" style="width: 100%">
+						<div style="display: flex;" class="mb10" v-for="(item, index) in pointList" :key="index">
+							<el-input v-model="item.position" :disabled="!item.editFalg" @keydown="onLocalChange(item, index)" @change="onLocalChange(item, index)" placeholder="请输入关键字进行搜索" clearable style="flex: 1; margin-right: 10px"></el-input>
+							<span>排序:</span>
+							<el-input-number v-model="item.sort" :controls="false" :disabled="!item.editFalg" placeholder="排序" clearable style="width: 100px; margin-right: 10px"></el-input-number>
+						</div>
+					</div>
+        </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 } from 'vue';
+import api from '/@/api/heatStation';
+import { ElMessage } from 'element-plus';
+interface Point {
+	sort?: number;
+	lnt: number;
+	lat: number
+}
+interface RuleFormState {
+	id?: number;
+	name: string;
+	code: string;
+	stationId: string;
+	loopTypes: string;
+	energyTypes: string;
+	heatingObject: string;
+	heatingTypes: string;
+	heatingArea: string;
+	forRealArea: string;
+	viaPoint: Array<Point>;
+	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: '',
+				viaPoint: [],
+        status: 1
+			},
+			treeData: [],
+      pointList: [] as any
+		})
+		// 打开弹窗
+		const openDialog = (row: RuleFormState | null) => {
+			resetForm()
+			queryTree()
+			if (row) {
+				(state.ruleForm as any).id = row.id
+				getDetail()
+			}
+			state.dialogVisible = true
+		}
+		const resetForm = () => {
+			state.ruleForm = {
+				id: 0,
+				name: '',
+        code: '',
+        stationId: '',
+        loopTypes: '',
+        energyTypes: '',
+        heatingObject: '',
+        heatingTypes: '',
+        heatingArea: '',
+        forRealArea: '',
+				viaPoint: [],
+        decade: '',
+        status: 1
+			}
+		}
+		// 关闭弹窗
+		const closeDialog = () => {
+			state.dialogVisible = false
+		}
+		// 取消
+		const onCancel = () => {
+			closeDialog()
+			state.pointList = []
+		}
+		const queryTree = () => {
+			api.heatStation.getList({
+					name: '',
+					code: '',
+					status: -1
+				})
+				.then((res: any) => {
+					state.treeData = res || [];
+				});
+		};
+		const getDetail = () => {
+			api.loop.detail(state.ruleForm.id)
+				.then((res: any) => {
+					state.ruleForm = {
+						...res
+					}
+					state.pointList = state.ruleForm.viaPoint.map((item: any) => ({
+						...item,
+						editFlag: false
+					}))
+				})
+		}
+
+		return {
+			openDialog,
+			closeDialog,
+			onCancel,
+			formRef,
+			...toRefs(state)
+		}
+	}
+})
+</script>

+ 278 - 0
src/views/heatingDistrict/heatingDistrictManage/children/resident/component/edit.vue

@@ -0,0 +1,278 @@
+<template>
+	<div class="system-edit-dic-container">
+		<el-dialog :title="(ruleForm.id !== 0 ? '修改' : '添加') + '住户'" v-model="dialogVisible" width="550px">
+			<el-form :model="ruleForm" ref="formRef" :rules="rules" size="default" label-width="110px">
+				<el-form-item label="所属组织" prop="organizationId">
+					<el-tree-select
+						v-model="ruleForm.organizationId"
+						:data="orgList"
+						: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="">
+					<el-tree-select
+						v-model="ruleForm.heatStaId"
+						:data="heatList"
+						: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="plotId">
+					<el-select v-model="ruleForm.plotId" @change="onPlotChange" placeholder="选择小区名称" filterable clearable size="default" style="width: 100%">
+						<el-option
+							v-for="item in plotList"
+							:key="item.id"
+							:label="item.name"
+							:value="item.id">
+						</el-option>
+					</el-select>
+				</el-form-item>
+				<el-form-item label="楼宇名称" prop="floorId">
+					<el-select v-model="ruleForm.floorId" @change="onFloorChange" placeholder="选择楼宇名称" filterable clearable size="default" style="width: 100%">
+						<el-option
+							v-for="item in floorList"
+							:key="item.id"
+							:label="item.name"
+							:value="item.id">
+						</el-option>
+					</el-select>
+				</el-form-item>
+				<el-form-item label="单元名称" prop="unitId">
+					<el-select v-model="ruleForm.unitId" placeholder="选择单元名称" filterable clearable size="default" style="width: 100%">
+						<el-option
+							v-for="item in unitList"
+							:key="item.id"
+							:label="item.name"
+							:value="item.id">
+						</el-option>
+					</el-select>
+				</el-form-item>
+				<el-form-item label="住户姓名" prop="name">
+					<el-input v-model="ruleForm.name" placeholder="请输入住户姓名" />
+				</el-form-item>
+				<el-form-item label="楼层" prop="floorLevel">
+					<el-input v-model="ruleForm.floorLevel" placeholder="请输入楼层" />
+				</el-form-item>
+				<el-form-item label="房间号" prop="roomNumber">
+					<el-input v-model="ruleForm.roomNumber" placeholder="请输入房间号" />
+				</el-form-item>
+				<el-form-item label="电话号码" prop="phone">
+					<el-input v-model="ruleForm.phone" placeholder="请输入电话号码" />
+				</el-form-item>
+				<el-form-item label="建筑面积" prop="buildingArea">
+					<el-input v-model="ruleForm.buildingArea" placeholder="请输入建筑面积" />
+				</el-form-item>
+				<el-form-item label="实供面积" prop="forRealArea">
+					<el-input v-model="ruleForm.forRealArea" 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="remark">
+					<el-input type="textarea" :rows="8" v-model="ruleForm.remark" placeholder="请输入备注" />
+				</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/heatingDistrict';
+import heatApi from '/@/api/heatStation';
+import { ElMessage } from 'element-plus';
+interface RuleFormState {
+	id?: number;
+	name: string;
+	organizationId: string;
+}
+
+export default defineComponent({
+	name: 'edit',
+	setup(prop, { emit }) {
+		const formRef = ref<HTMLElement | null>(null);
+		const state = reactive({
+			dialogVisible: false,
+			ruleForm: {
+				id: 0,
+				organizationId: '',
+				heatStaId: '',
+				plotId: '',
+				floorId: '',
+				unitId: '',
+				name: '',
+				floorLevel: '',
+				roomNumber: '',
+				phone: '',
+				buildingArea: '',
+				forRealArea: '',
+				remark: '',
+				status: 1
+			},
+			rules: {
+				name: [{ required: true, message: '住户名称不能为空', trigger: ['blur', 'change'] }],
+				organizationId: [{ required: true, message: '所属组织不能为空', trigger: ['blur', 'change'] }],
+				plotId: [{ required: true, message: '小区名称不能为空', trigger: ['blur', 'change'] }],
+				floorId: [{ required: true, message: '楼宇名称不能为空', trigger: ['blur', 'change'] }],
+				unitId: [{ required: true, message: '单元名称不能为空', trigger: ['blur', 'change'] }],
+				heatStaId: [{ required: true, message: '所属换热站不能为空', trigger: ['blur', 'change'] }],
+				floorLevel: [{ required: true, message: '楼层不能为空', trigger: ['blur', 'change'] }],
+				roomNumber: [{ required: true, message: '房间号不能为空', trigger: ['blur', 'change'] }],
+				phone: [{ required: true, message: '手机号码不能为空', trigger: ['blur', 'change'] }],
+				forRealArea: [{ required: true, message: '实供面积不能为空', trigger: ['blur', 'change'] }],
+				buildingArea: [{ required: true, message: '建筑面积不能为空', trigger: ['blur', 'change'] }],
+			},
+			orgList: [],
+			plotList: [],
+			floorList: [],
+			unitList: [],
+			heatList: []
+		})
+		// 打开弹窗
+		const openDialog = (row: RuleFormState | null) => {
+			resetForm()
+			queryTree()
+			if (row) {
+				(state.ruleForm as any).id = row.id
+				getDetail()
+			}
+			state.dialogVisible = true
+		}
+		const resetForm = () => {
+			state.ruleForm = {
+				id: 0,
+				organizationId: '',
+				heatStaId: '',
+				plotId: '',
+				floorId: '',
+				unitId: '',
+				name: '',
+				floorLevel: '',
+				roomNumber: '',
+				phone: '',
+				buildingArea: '',
+				forRealArea: '',
+				remark: '',
+				status: 1
+			}
+		}
+		// 关闭弹窗
+		const closeDialog = () => {
+			state.dialogVisible = false;
+			(formRef.value as any).clearValidate()
+		}
+		// 取消
+		const onCancel = () => {
+			closeDialog()
+		}
+		const queryTree = () => {
+			heatApi.heatStation.getList({
+					name: '',
+					code: '',
+					status: -1
+				})
+				.then((res: any) => {
+					state.heatList = res || [];
+				});
+		};
+		const getDetail = () => {
+			api.resident.detail(state.ruleForm.id)
+				.then((res: any) => {
+					state.ruleForm = {
+						...res,
+						heatStaId: res.heatStaId || ''
+					}
+				})
+		}
+		// 获取楼宇
+		const getFloorList = () => {
+			api.floor.allList({ plotId: state.ruleForm.plotId })
+				.then((res: any) => {
+					state.floorList = res.Info || []
+				})
+		}
+		// 获取单元
+		const getUnitList = () => {
+			api.unit.getListByFloorId({ floorId: state.ruleForm.floorId })
+				.then((res: any) => {
+					(state.unitList as any) = res ? [res] : []
+				})
+		}
+		const onPlotChange = () => { 
+			state.floorList = []
+			state.unitList = []
+			state.ruleForm.floorId = ''
+			state.ruleForm.unitId = ''
+			if (state.ruleForm.plotId) {
+				getFloorList()
+			}
+		}
+		const onFloorChange = () => {
+			state.unitList = []
+			state.ruleForm.unitId = ''
+			if (state.ruleForm.floorId) {
+				getUnitList()
+			}
+		}
+		// 新增
+		const onSubmit = () => {
+			const formWrap = unref(formRef) as any
+			if (!formWrap) return;
+			formWrap.validate((valid: boolean) => {
+				if (valid) {
+					let params = { ...state.ruleForm }
+
+					if (params.id) {
+						//修改
+						api.resident.edit(params).then(() => {
+							ElMessage.success('单元修改成功')
+							closeDialog() // 关闭弹窗
+							emit('queryList')
+						})
+					} else {
+						//添加
+						api.resident.add(params).then(() => {
+							ElMessage.success('单元添加成功')
+							closeDialog() // 关闭弹窗
+							emit('queryList')
+						})
+					}
+				}
+			})
+		}
+
+		return {
+			openDialog,
+			closeDialog,
+			onCancel,
+			onSubmit,
+			formRef,
+			onPlotChange,
+			onFloorChange,
+			...toRefs(state)
+		}
+	}
+})
+</script>

+ 318 - 0
src/views/heatingDistrict/heatingDistrictManage/children/resident/index.vue

@@ -0,0 +1,318 @@
+<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="organizationId">
+						<el-tree-select
+							v-model="tableData.param.organizationId"
+							:data="orgList"
+							:props="{
+								label: 'name',
+								children: 'children'
+							}"
+							placeholder="请选择"
+							node-key="id"
+							:clearable="true"
+							check-strictly
+							style="width: 100%;"
+							:render-after-expand="true"
+							size="default"
+						/>
+          </el-form-item>
+          <el-form-item label="小区名称" prop="plotId">
+            <el-select v-model="tableData.param.plotId" @change="onPlotChange" placeholder="选择小区名称" filterable clearable size="default">
+							<el-option
+								v-for="item in plotList"
+								:key="item.id"
+								:label="item.name"
+								:value="item.id">
+							</el-option>
+						</el-select>
+          </el-form-item>
+          <el-form-item label="楼宇名称" prop="floorId">
+            <el-select v-model="tableData.param.floorId" @change="onFloorChange" placeholder="选择楼宇名称" filterable clearable size="default">
+							<el-option
+								v-for="item in floorList"
+								:key="item.id"
+								:label="item.name"
+								:value="item.id">
+							</el-option>
+						</el-select>
+          </el-form-item>
+          <el-form-item label="单元名称" prop="unitId">
+            <el-select v-model="tableData.param.unitId" placeholder="选择单元名称" filterable clearable size="default">
+							<el-option
+								v-for="item in unitList"
+								:key="item.id"
+								:label="item.name"
+								:value="item.id">
+							</el-option>
+						</el-select>
+          </el-form-item>
+          <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>
+            <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="onOpenDialog()">
+              <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" v-loading="tableData.loading" style="width: 100%" >
+        <!-- <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="" min-width="100">
+          <template #default="{ row }">
+            {{ row.organizationInfo.name }}
+          </template>
+        </el-table-column>
+        <el-table-column label="小区名称" prop="" min-width="100">
+          <template #default="{ row }">
+            {{ row.plotInfo.name }}
+          </template>
+        </el-table-column>
+        <el-table-column label="楼宇名称" prop="" min-width="100">
+          <template #default="{ row }">
+            {{ row.floorInfo.name }}
+          </template>
+        </el-table-column>
+	    	<el-table-column label="单元名称" prop="name" min-width="100">
+          <template #default="{ row }">
+            {{ row.unitInfo.name }}
+          </template>
+        </el-table-column>
+	    	<el-table-column label="单元号" prop="number" min-width="100">
+          <template #default="{ row }">
+            {{ row.unitInfo.number }}
+          </template>
+        </el-table-column>
+	    	<el-table-column label="住户姓名" prop="name" min-width="100" />
+	    	<el-table-column label="楼层" prop="floorLevel" min-width="100" />
+	    	<el-table-column label="房间号" prop="roomNumber" min-width="100" />
+	    	<el-table-column label="电话号码" prop="phone" min-width="100" />
+	    	<el-table-column label="建筑面积" prop="buildingArea" min-width="100" />
+	    	<el-table-column label="实供面积" prop="forRealArea" min-width="100" />
+	    	<el-table-column label="更新时间" prop="createdAt" width="180"/>
+				<el-table-column prop="status" label="启用状态" width="120" align="center">
+					<template #default="scope">
+						<el-switch v-model="scope.row.status" inline-prompt :active-value="1" :inactive-value="0" active-text="启" inactive-text="禁" @change="handleStatusChange(scope.row)">
+						</el-switch>
+					</template>
+				</el-table-column>
+        <el-table-column label="操作" width="200" align="center" fixed="right">
+          <template #default="scope">
+            <el-button size="small" text type="warning" @click="onOpenDialog(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/heatingDistrict';
+import systemApi from '/@/api/system';
+
+export default defineComponent({
+	name: 'loop',
+	components: { EditDic,Detail },
+	setup() {
+		const addDicRef = ref();
+		const editDicRef = ref();
+		const detailRef=ref();
+		const queryRef = ref();
+		const state = reactive({
+			ids: [],
+			tableData: {
+				data: [],
+				total: 0,
+				loading: false,
+				param: {
+					pageNum: 1,
+					pageSize: 10,
+					name: '',
+					plotId: '',
+					floorId: '',
+					unitId: '',
+					organizationId: '',
+					status: -1
+				},
+			},
+		});
+		// 组织
+		const orgList = ref([])
+		// 小区
+		const plotList = ref([])
+		// 楼宇
+		const floorList = ref([])
+		// 单元
+		const unitList = ref([])
+		// 初始化表格数据
+		const initTableData = () => {
+			queryList();
+		};
+		// 获取组织
+		const getOrgList = () => {
+			systemApi.org.getList({ name: '', status: -1 }).then((res: any) => {
+				orgList.value = res;
+			});
+		}
+		// 获取区域
+		const getPlotList = () => {
+			api.regionalManage.allList({})
+				.then((res: any) => {
+					plotList.value = res.Info || []
+				})
+		}
+		// 获取楼宇
+		const getFloorList = () => {
+			api.floor.allList({})
+				.then((res: any) => {
+					floorList.value = res.Info || []
+				})
+		}
+		// 获取单元
+		const getUnitList = () => {
+			api.unit.getListByFloorId({ floorId: state.tableData.param.floorId })
+				.then((res: any) => {
+					(unitList.value as any) = res ? [res] : []
+				})
+		}
+		const queryList = () => {
+			state.tableData.loading = true
+			api.resident.getList(state.tableData.param).then((res: any) => {
+				console.log(res);
+				state.tableData.data = res.Data || [];
+				state.tableData.total = res.Total;
+				state.tableData.loading = false
+			});
+		};
+		const onPlotChange = () => { 
+			floorList.value = []
+			unitList.value = []
+			state.tableData.param.floorId = ''
+			state.tableData.param.unitId = ''
+			if (state.tableData.param.plotId) {
+				getFloorList()
+			}
+		}
+		const onFloorChange = () => {
+			unitList.value = []
+			state.tableData.param.unitId = ''
+			if (state.tableData.param.floorId) {
+				getUnitList()
+			}
+		}
+		//查看详情
+		const onOpenDetail=(row: any)=>{
+			detailRef.value.openDialog(row);
+		}
+		// 打开新增修改弹窗
+		const onOpenDialog = (row: any) => {
+			editDicRef.value.orgList = orgList.value
+			editDicRef.value.plotList = plotList.value
+			editDicRef.value.openDialog(row);
+		};
+		
+		// 状态修改
+		const handleStatusChange = (row: any) => {
+			let text = row.status === 1 ? '启用' : '停用';
+			ElMessageBox.confirm('确认要"' + text + '":"' + row.name + '"住户吗?', '警告', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				type: 'warning',
+			})
+				.then(function () {
+					return api.resident.setStatus(row.id, row.status);
+				})
+				.then(() => {
+					ElMessage.success(text + '成功');
+				})
+				.catch(function () {
+					row.status = row.status === 0 ? 1 : 0;
+				});
+		};
+		// 删除产品
+		const onRowDel = (row: any) => {
+			let msg = `此操作将永久删除住户:“${row.name}”,是否继续?`;
+			ElMessageBox.confirm(msg, '提示', {
+				confirmButtonText: '确认',
+				cancelButtonText: '取消',
+				type: 'warning',
+			})
+				.then(() => {
+					api.resident.del(row.id).then(() => {
+						ElMessage.success('删除成功');
+						queryList();
+					});
+				})
+				.catch(() => {});
+		};
+		// 页面加载时
+		onMounted(() => {
+			initTableData();
+			getOrgList();
+			getPlotList()
+			// getFloorList()
+			// getUnitList()
+		});
+		/** 重置按钮操作 */
+		const resetQuery = (formEl: FormInstance | undefined) => {
+			if (!formEl) return;
+			formEl.resetFields();
+			queryList();
+		};
+
+		return {
+			addDicRef,
+			editDicRef,
+			detailRef,
+			queryRef,
+			onOpenDetail,
+			onOpenDialog,
+			onRowDel,
+			queryList,
+			resetQuery,
+			orgList,
+			plotList,
+			floorList,
+			unitList,
+			onPlotChange,
+			onFloorChange,
+			handleStatusChange,
+			...toRefs(state),
+		};
+	},
+});
+</script>

+ 200 - 0
src/views/heatingDistrict/heatingDistrictManage/children/unit/component/detail.vue

@@ -0,0 +1,200 @@
+<template>
+	<div class="system-edit-dic-container">
+		<el-dialog :title="'环路详情'" v-model="dialogVisible" width="950px">
+			<el-form :model="ruleForm" ref="formRef" size="default" label-width="110px">
+				<el-form-item label="环路名称" prop="name">
+					{{ ruleForm.name }}
+				</el-form-item>
+				<el-form-item label="环路编号" prop="code">
+					{{ ruleForm.code }}
+				</el-form-item>
+				<el-form-item label="所属换热站" prop="stationId">
+          {{ ruleForm.stationId }}
+					<!-- <el-tree-select
+						v-model="ruleForm.stationId"
+						: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="loopTypes">
+          {{ ruleForm.loopTypes === 1 ? '一网' : '二网' }}
+        </el-form-item>
+        <el-form-item label="节能类型" prop="energyTypes">
+          {{ ruleForm.energyTypes === 1 ? '节能' : '' }}
+        </el-form-item>
+        <el-row :gutter="10">
+          <el-col :span="12">
+            <el-form-item label="供暖对象" prop="heatingObject">
+              {{ ruleForm.heatingObject === 1 ? '公建' : '居民' }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="供暖类型" prop="heatingTypes">
+              {{ ruleForm.heatingTypes === 1 ? '地暖' : '暖气片' }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="10">
+          <el-col :span="12">
+            <el-form-item label="供暖面积" prop="heatingArea">
+              {{ ruleForm.heatingArea }}
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="实际面积" prop="forRealArea">
+              {{ ruleForm.forRealArea }}
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="环路年代" prop="decade">
+          {{ ruleForm.decade }}
+        </el-form-item>
+				<el-form-item label="状态" prop="status">
+          {{ ruleForm.decade === 1 ? '在线' : '不在线' }}
+				</el-form-item>
+        <el-form-item label="路线信息" prop="">
+					<div class="mb10" style="width: 100%">
+						<div style="display: flex;" class="mb10" v-for="(item, index) in pointList" :key="index">
+							<el-input v-model="item.position" :disabled="!item.editFalg" @keydown="onLocalChange(item, index)" @change="onLocalChange(item, index)" placeholder="请输入关键字进行搜索" clearable style="flex: 1; margin-right: 10px"></el-input>
+							<span>排序:</span>
+							<el-input-number v-model="item.sort" :controls="false" :disabled="!item.editFalg" placeholder="排序" clearable style="width: 100px; margin-right: 10px"></el-input-number>
+						</div>
+					</div>
+        </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 } from 'vue';
+import api from '/@/api/heatStation';
+import { ElMessage } from 'element-plus';
+interface Point {
+	sort?: number;
+	lnt: number;
+	lat: number
+}
+interface RuleFormState {
+	id?: number;
+	name: string;
+	code: string;
+	stationId: string;
+	loopTypes: string;
+	energyTypes: string;
+	heatingObject: string;
+	heatingTypes: string;
+	heatingArea: string;
+	forRealArea: string;
+	viaPoint: Array<Point>;
+	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: '',
+				viaPoint: [],
+        status: 1
+			},
+			treeData: [],
+      pointList: [] as any
+		})
+		// 打开弹窗
+		const openDialog = (row: RuleFormState | null) => {
+			resetForm()
+			queryTree()
+			if (row) {
+				(state.ruleForm as any).id = row.id
+				getDetail()
+			}
+			state.dialogVisible = true
+		}
+		const resetForm = () => {
+			state.ruleForm = {
+				id: 0,
+				name: '',
+        code: '',
+        stationId: '',
+        loopTypes: '',
+        energyTypes: '',
+        heatingObject: '',
+        heatingTypes: '',
+        heatingArea: '',
+        forRealArea: '',
+				viaPoint: [],
+        decade: '',
+        status: 1
+			}
+		}
+		// 关闭弹窗
+		const closeDialog = () => {
+			state.dialogVisible = false
+		}
+		// 取消
+		const onCancel = () => {
+			closeDialog()
+			state.pointList = []
+		}
+		const queryTree = () => {
+			api.heatStation.getList({
+					name: '',
+					code: '',
+					status: -1
+				})
+				.then((res: any) => {
+					state.treeData = res || [];
+				});
+		};
+		const getDetail = () => {
+			api.loop.detail(state.ruleForm.id)
+				.then((res: any) => {
+					state.ruleForm = {
+						...res
+					}
+					state.pointList = state.ruleForm.viaPoint.map((item: any) => ({
+						...item,
+						editFlag: false
+					}))
+				})
+		}
+
+		return {
+			openDialog,
+			closeDialog,
+			onCancel,
+			formRef,
+			...toRefs(state)
+		}
+	}
+})
+</script>

+ 221 - 0
src/views/heatingDistrict/heatingDistrictManage/children/unit/component/edit.vue

@@ -0,0 +1,221 @@
+<template>
+	<div class="system-edit-dic-container">
+		<el-dialog :title="(ruleForm.id !== 0 ? '修改' : '添加') + '单元'" v-model="dialogVisible" width="550px">
+			<el-form :model="ruleForm" ref="formRef" :rules="rules" size="default" label-width="110px">
+				<el-form-item label="所属组织" prop="organizationId">
+					<el-tree-select
+						v-model="ruleForm.organizationId"
+						:data="orgList"
+						:props="{
+							label: 'name',
+							children: 'children'
+						}"
+						node-key="id"
+						:clearable="true"
+						check-strictly
+						style="width: 100%;"
+						:render-after-expand="true"
+					/>
+				</el-form-item>
+				<!-- heatStaId -->
+				<el-form-item label="所属换热站" prop="">
+					<el-tree-select
+						v-model="ruleForm.heatStaId"
+						:data="heatList"
+						: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="plotId">
+					<el-select v-model="ruleForm.plotId" @change="onPlotChange" placeholder="选择小区名称" filterable clearable size="default" style="width: 100%">
+						<el-option
+							v-for="item in plotList"
+							:key="item.id"
+							:label="item.name"
+							:value="item.id">
+						</el-option>
+					</el-select>
+				</el-form-item>
+				<el-form-item label="楼宇名称" prop="floorId">
+					<el-select v-model="ruleForm.floorId" placeholder="选择楼宇名称" filterable clearable size="default" style="width: 100%">
+						<el-option
+							v-for="item in floorList"
+							:key="item.id"
+							:label="item.name"
+							:value="item.id">
+						</el-option>
+					</el-select>
+				</el-form-item>
+				<el-form-item label="单元名称" prop="name">
+					<el-input v-model="ruleForm.name" placeholder="请输入单元名称" />
+				</el-form-item>
+				<el-form-item label="单元号" prop="number">
+					<el-input v-model="ruleForm.number" 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="remark">
+					<el-input type="textarea" :rows="8" v-model="ruleForm.remark" placeholder="请输入备注" />
+				</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/heatingDistrict';
+import heatApi from '/@/api/heatStation';
+import { ElMessage } from 'element-plus';
+
+export default defineComponent({
+	name: 'edit',
+	setup(prop, { emit }) {
+		const formRef = ref<HTMLElement | null>(null);
+		const state = reactive({
+			dialogVisible: false,
+			ruleForm: {
+				id: 0,
+				name: '',
+        organizationId: '',
+        plotId: '',
+        floorId: '',
+        heatStaId: '',
+        number: '',
+        remark: '',
+				status: 1
+			},
+			rules: {
+				name: [{ required: true, message: '单元名称不能为空', trigger: ['blur', 'change'] }],
+				organizationId: [{ required: true, message: '所属组织不能为空', trigger: ['blur', 'change'] }],
+				plotId: [{ required: true, message: '小区名称不能为空', trigger: ['blur', 'change'] }],
+				floorId: [{ required: true, message: '楼宇名称不能为空', trigger: ['blur', 'change'] }],
+				heatStaId: [{ required: true, message: '所属换热站不能为空', trigger: ['blur', 'change'] }],
+				number: [{ required: true, message: '楼号不能为空', trigger: ['blur', 'change'] }],
+			},
+			orgList: [],
+			plotList: [],
+			floorList: [],
+			heatList: []
+		})
+		// 打开弹窗
+		const openDialog = (row: any) => {
+			resetForm()
+			queryTree()
+			if (row) {
+				(state.ruleForm as any).id = row.id;
+				(state.ruleForm as any).plotId = row.plotId;
+				getDetail()
+				getFloorList()
+			}
+			state.dialogVisible = true
+		}
+		const resetForm = () => {
+			state.ruleForm = {
+				id: 0,
+				name: '',
+        organizationId: '',
+        plotId: '',
+        floorId: '',
+        heatStaId: '',
+        number: '',
+        remark: '',
+				status: 1
+			}
+		}
+		// 关闭弹窗
+		const closeDialog = () => {
+			state.dialogVisible = false;
+			(formRef.value as any).clearValidate()
+		}
+		// 取消
+		const onCancel = () => {
+			closeDialog()
+		}
+		const queryTree = () => {
+			heatApi.heatStation.getList({
+					name: '',
+					code: '',
+					status: -1
+				})
+				.then((res: any) => {
+					state.heatList = res || [];
+				});
+		};
+		const getDetail = () => {
+			api.unit.detail(state.ruleForm.id)
+				.then((res: any) => {
+					state.ruleForm = {
+						...res,
+						heatStaId: res.heatStaId || ''
+					}
+				})
+		}
+		const onPlotChange = () => {
+			state.floorList = []
+			state.ruleForm.floorId = ''
+			if (state.ruleForm.plotId) {
+				getFloorList()
+			}
+		}
+		// 获取楼宇
+		const getFloorList = () => {
+			api.floor.allList({ plotId: state.ruleForm.plotId })
+				.then((res: any) => {
+					state.floorList = res.Info || []
+				})
+		}
+		// 新增
+		const onSubmit = () => {
+			const formWrap = unref(formRef) as any
+			if (!formWrap) return;
+			formWrap.validate((valid: boolean) => {
+				if (valid) {
+					let params = { ...state.ruleForm }
+
+					if (params.id) {
+						//修改
+						api.unit.edit(params).then(() => {
+							ElMessage.success('单元修改成功')
+							closeDialog() // 关闭弹窗
+							emit('queryList')
+						})
+					} else {
+						//添加
+						api.unit.add(params).then(() => {
+							ElMessage.success('单元添加成功')
+							closeDialog() // 关闭弹窗
+							emit('queryList')
+						})
+					}
+				}
+			})
+		}
+
+		return {
+			openDialog,
+			closeDialog,
+			onCancel,
+			onSubmit,
+			formRef,
+			onPlotChange,
+			...toRefs(state)
+		}
+	}
+})
+</script>

+ 260 - 0
src/views/heatingDistrict/heatingDistrictManage/children/unit/index.vue

@@ -0,0 +1,260 @@
+<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="organizationId">
+						<el-tree-select
+							v-model="tableData.param.organizationId"
+							:data="orgList"
+							:props="{
+								label: 'name',
+								children: 'children'
+							}"
+							placeholder="请选择"
+							node-key="id"
+							:clearable="true"
+							check-strictly
+							style="width: 100%;"
+							:render-after-expand="true"
+							size="default"
+						/>
+          </el-form-item>
+          <el-form-item label="小区名称" prop="plotId">
+            <el-select v-model="tableData.param.plotId" @change="onPlotChange" placeholder="选择小区名称" filterable clearable size="default">
+							<el-option
+								v-for="item in plotList"
+								:key="item.id"
+								:label="item.name"
+								:value="item.id">
+							</el-option>
+						</el-select>
+          </el-form-item>
+          <el-form-item label="楼宇名称" prop="floorId">
+            <el-select v-model="tableData.param.floorId" placeholder="选择楼宇名称" filterable clearable size="default">
+							<el-option
+								v-for="item in floorList"
+								:key="item.id"
+								:label="item.name"
+								:value="item.id">
+							</el-option>
+						</el-select>
+          </el-form-item>
+          <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>
+            <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="onOpenDialog()">
+              <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" v-loading="tableData.loading" style="width: 100%" >
+        <!-- <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="organizationInfo.name" min-width="100" />
+        <el-table-column label="小区名称" prop="plotInfo.name" min-width="100" />
+        <el-table-column label="楼宇名称" prop="floorInfo.name" min-width="100" />
+        <el-table-column label="楼号" prop="floorInfo.number" min-width="100" />
+	    	<el-table-column label="单元名称" prop="name" min-width="100" />
+	    	<el-table-column label="单元号" prop="number" min-width="100" />
+	    	<el-table-column label="更新时间" prop="updatedAt" width="180" />
+				<el-table-column prop="status" label="启用状态" width="120" align="center">
+					<template #default="scope">
+						<el-switch v-model="scope.row.status" inline-prompt :active-value="1" :inactive-value="0" active-text="启" inactive-text="禁" @change="handleStatusChange(scope.row)">
+						</el-switch>
+					</template>
+				</el-table-column>
+        <el-table-column label="操作" width="200" align="center" fixed="right">
+          <template #default="scope">
+            <el-button size="small" text type="warning" @click="onOpenDialog(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/heatingDistrict';
+import systemApi from '/@/api/system';
+
+export default defineComponent({
+	name: 'loop',
+	components: { EditDic,Detail },
+	setup() {
+		const addDicRef = ref();
+		const editDicRef = ref();
+		const detailRef=ref();
+		const queryRef = ref();
+		const state = reactive({
+			ids: [],
+			tableData: {
+				data: [],
+				total: 0,
+				loading: false,
+				param: {
+					pageNum: 1,
+					pageSize: 10,
+					name: '',
+					plotId: '',
+					floorId: '',
+					organizationId: '',
+					status: -1
+				},
+			},
+		});
+		// 组织
+		const orgList = ref([])
+		// 小区
+		const plotList = ref([])
+		// 楼宇
+		const floorList = ref([])
+		// 初始化表格数据
+		const initTableData = () => {
+			queryList();
+		};
+		// 获取组织
+		const getOrgList = () => {
+			systemApi.org.getList({ name: '', status: -1 }).then((res: any) => {
+				orgList.value = res;
+			});
+		}
+		// 获取区域
+		const getPlotList = () => {
+			api.regionalManage.allList({})
+				.then((res: any) => {
+					plotList.value = res.Info || []
+				})
+		}
+		// 获取楼宇
+		const getFloorList = () => {
+			api.floor.allList({ plotId: state.tableData.param.plotId })
+				.then((res: any) => {
+					floorList.value = res.Info || []
+				})
+		}
+		const queryList = () => {
+			state.tableData.loading = true
+			api.unit.getList(state.tableData.param).then((res: any) => {
+				console.log(res);
+				state.tableData.data = res.Data || [];
+				state.tableData.total = res.Total;
+				state.tableData.loading = false
+			});
+		};
+		const onPlotChange = () => {
+			floorList.value = []
+			state.tableData.param.floorId = ''
+			if (state.tableData.param.plotId) {
+				getFloorList()
+			}
+		}
+		//查看详情
+		const onOpenDetail=(row: any)=>{
+			detailRef.value.openDialog(row);
+		}
+		// 打开新增修改弹窗
+		const onOpenDialog = (row: any) => {
+			editDicRef.value.orgList = orgList.value
+			editDicRef.value.plotList = plotList.value
+			editDicRef.value.openDialog(row);
+		};
+		
+		// 状态修改
+		const handleStatusChange = (row: any) => {
+			let text = row.status === 1 ? '启用' : '停用';
+			ElMessageBox.confirm('确认要"' + text + '":"' + row.name + '"单元吗?', '警告', {
+				confirmButtonText: '确定',
+				cancelButtonText: '取消',
+				type: 'warning',
+			})
+				.then(function () {
+					return api.unit.setStatus(row.id, row.status);
+				})
+				.then(() => {
+					ElMessage.success(text + '成功');
+				})
+				.catch(function () {
+					row.status = row.status === 0 ? 1 : 0;
+				});
+		};
+		// 删除产品
+		const onRowDel = (row: any) => {
+			let msg = `此操作将永久删除单元:“${row.name}”,是否继续?`;
+			ElMessageBox.confirm(msg, '提示', {
+				confirmButtonText: '确认',
+				cancelButtonText: '取消',
+				type: 'warning',
+			})
+				.then(() => {
+					api.unit.del(row.id).then(() => {
+						ElMessage.success('删除成功');
+						queryList();
+					});
+				})
+				.catch(() => {});
+		};
+		// 页面加载时
+		onMounted(() => {
+			initTableData();
+			getOrgList();
+			getPlotList()
+		});
+		/** 重置按钮操作 */
+		const resetQuery = (formEl: FormInstance | undefined) => {
+			if (!formEl) return;
+			formEl.resetFields();
+			queryList();
+		};
+
+		return {
+			addDicRef,
+			editDicRef,
+			detailRef,
+			queryRef,
+			onOpenDetail,
+			onOpenDialog,
+			onRowDel,
+			queryList,
+			resetQuery,
+			orgList,
+			plotList,
+			floorList,
+			onPlotChange,
+			handleStatusChange,
+			...toRefs(state),
+		};
+	},
+});
+</script>

+ 110 - 0
src/views/heatingDistrict/heatingDistrictManage/index.vue

@@ -0,0 +1,110 @@
+<template>
+  <div class="page-container">
+		<div class="left-panel">
+  		<el-input v-model="filterText" size="default" placeholder="搜索区域" />
+			<el-tree
+				:data="treeList"
+				node-key="id"
+				default-expand-all
+				:props="{
+					children: 'children'
+				}"
+				@node-click="onNodeClick"
+				:expand-on-click-node="false"
+			>
+				<template #default="{ node, data }">
+					<span class="custom-tree-node" :class="{ active: data.id === curNode.id }">
+						<span>{{ data.orgName }}</span>
+					</span>
+				</template>
+			</el-tree>
+		</div>
+		<div class="right-panel">
+			<!-- 小区 -->
+			<Regional v-if="curNode.orgType === 'org'" :organizationId="curNode.id"/>
+			<!-- 楼宇 -->
+			<Floor v-else-if="curNode.orgType === 'plot'" :organizationId="curNode.organizationId" :plotId="curNode.id"/>
+			<!-- 单元 -->
+			<Unit v-else-if="curNode.orgType === 'floor'" :organizationId="curNode.organizationId" :plotId="curNode.id"/>
+			<!-- 住户 -->
+			<Resident v-else-if="curNode.orgType === 'unit'" :organizationId="curNode.organizationId" :plotId="curNode.id"/>
+		</div>
+  </div>
+</template>
+
+<script lang="ts">
+import { toRefs, reactive, onMounted, ref, defineComponent } from 'vue';
+import api from '/@/api/heatingDistrict';
+import Regional from './children/regional/index.vue'
+import Floor from './children/floor/index.vue'
+import Unit from './children/unit/index.vue'
+import Resident from './children/resident/index.vue'
+
+export default defineComponent({
+	name: '',
+	components: {
+		Regional,
+		Floor,
+		Unit,
+		Resident
+	},
+	setup() {
+		const treeList = ref([])
+		const state = reactive({
+			filterText: '',
+			curNode: {}
+		});
+		// 获取区域树
+		const getTreeData = () => {
+			api.heatingDistrict.getTree({})
+				.then((res: any) => {
+					treeList.value = res || []
+					state.curNode = treeList.value[0]
+				})
+		}
+		const onNodeClick = (data: any, node: any) => {
+			console.log(data)
+			state.curNode = data
+			// console.log(node)
+		}
+
+		// 页面加载时
+		onMounted(() => {
+			getTreeData()
+		});
+
+
+		return {
+			treeList,
+			onNodeClick,
+			...toRefs(state),
+		};
+	},
+});
+</script>
+
+<style lang="scss" scoped>
+.page-container {
+	display: grid;
+	grid-template-columns: 250px 1fr;
+	background-color: #fff;
+	border: 1px solid #ddd;
+	.left-panel {
+		padding: 20px;
+	}
+	.right-panel {
+		display: flex;
+		flex-direction: column;
+		padding: 20px;
+		border-left: 1px solid #ddd;
+	}
+}
+
+
+.custom-tree-node {
+  &.active {
+    color: var(--el-color-primary);
+		// background: var(--el-color-primary-light-9);
+  }
+}
+</style>