Просмотр исходного кода

1.增加泵站信息查询,修改,删除
2.增加管网信息查询,修改,删除

liziqian 1 месяц назад
Родитель
Сommit
91dba80eac

+ 63 - 0
src/api/pipeNetwork/pipeInfo.js

@@ -0,0 +1,63 @@
+import request from '@/utils/request'
+
+const urlPrefix = '/api/water/pipe'
+
+export function listPipeInfo(query) {
+  return request({
+    url: urlPrefix + '/page',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getPipeInfo(id) {
+  return request({
+    url: urlPrefix + '/' + id,
+    method: 'get'
+  })
+}
+
+export function addPipeInfo(data) {
+  return request({
+    url: urlPrefix,
+    method: 'post',
+    data: data
+  })
+}
+
+export function updatePipeInfo(data) {
+  return request({
+    url: urlPrefix,
+    method: 'put',
+    data: data
+  })
+}
+
+export function delPipeInfo(ids) {
+  return request({
+    url: urlPrefix + '/' + ids,
+    method: 'delete'
+  })
+}
+
+export function listRecyclePipeInfo(query) {
+  return request({
+    url: urlPrefix + '/recycle/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function restorePipeInfo(ids) {
+  return request({
+    url: urlPrefix + '/recycle/restore/' + ids,
+    method: 'post'
+  })
+}
+
+export function deletePhysicallyPipeInfo(ids) {
+  return request({
+    url: urlPrefix + '/recycle/delete/' + ids,
+    method: 'delete'
+  })
+}

+ 63 - 0
src/api/pipeNetwork/waterPumpStation.js

@@ -0,0 +1,63 @@
+import request from '@/utils/request'
+
+const urlPrefix = '/api/water/pumpStation'
+
+export function listPumpStation(query) {
+  return request({
+    url: urlPrefix + '/page',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getPumpStation(id) {
+  return request({
+    url: urlPrefix + '/' + id,
+    method: 'get'
+  })
+}
+
+export function addPumpStation(data) {
+  return request({
+    url: urlPrefix,
+    method: 'post',
+    data: data
+  })
+}
+
+export function updatePumpStation(data) {
+  return request({
+    url: urlPrefix,
+    method: 'put',
+    data: data
+  })
+}
+
+export function delPumpStation(ids) {
+  return request({
+    url: urlPrefix + '/' + ids,
+    method: 'delete'
+  })
+}
+
+export function listRecyclePumpStation(query) {
+  return request({
+    url: urlPrefix + '/recycle/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function restorePumpStation(ids) {
+  return request({
+    url: urlPrefix + '/recycle/restore/' + ids,
+    method: 'post'
+  })
+}
+
+export function deletePhysicallyPumpStation(ids) {
+  return request({
+    url: urlPrefix + '/recycle/delete/' + ids,
+    method: 'delete'
+  })
+}

+ 470 - 0
src/views/subSystem/basic/pipeInfo/index.vue

@@ -0,0 +1,470 @@
+<template>
+  <div class="app-container">
+    <!-- 搜索区域 -->
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="管网编号" prop="pipeCode">
+        <el-input v-model="queryParams.pipeCode" placeholder="请输入管网编号" clearable size="small" @keyup.enter="handleQuery" />
+      </el-form-item>
+      <el-form-item label="管网名称" prop="pipeName">
+        <el-input v-model="queryParams.pipeName" placeholder="请输入管网名称" clearable size="small" @keyup.enter="handleQuery" />
+      </el-form-item>
+      <el-form-item label="管道材质" prop="pipeMaterial">
+        <el-select v-model="queryParams.pipeMaterial" placeholder="请选择材质" clearable size="small" style="width: 120px">
+          <el-option label="铸铁" value="铸铁" />
+          <el-option label="PE" value="PE" />
+          <el-option label="钢管" value="钢管" />
+          <el-option label="球墨铸铁" value="球墨铸铁" />
+          <el-option label="PVC" value="PVC" />
+          <el-option label="混凝土" value="混凝土" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="管网状态" clearable size="small" style="width: 120px">
+          <el-option
+            v-for="dict in sysNormalDisable"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value" 
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="创建时间">
+        <el-date-picker
+          v-model="dateRange"
+          size="small"
+          style="width: 240px"
+          value-format="YYYY-MM-DD HH:mm:ss"
+          type="datetimerange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="Search" size="small" @click="handleQuery">搜索</el-button>
+        <el-button icon="Refresh" size="small" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- 操作按钮区域 -->
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button type="primary" plain icon="Plus" size="small" @click="handleAdd" v-hasPermi="['waterSupply:pipeInfo:add']">新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="Delete" size="small" :disabled="multiple" @click="handleDelete" v-hasPermi="['waterSupply:pipeInfo:remove']">删除</el-button>
+      </el-col>
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
+    </el-row>
+
+    <!-- 数据表格 -->
+    <el-table v-loading="loading" :data="tableData" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="管网编号" align="center" prop="pipeCode" :show-overflow-tooltip="true" min-width="120" />
+      <el-table-column label="管网名称" align="center" prop="pipeName" :show-overflow-tooltip="true" min-width="140" />
+      <el-table-column label="管道材质" align="center" prop="pipeMaterial" width="100">
+        <template #default="{ row }">
+          <el-tag :type="materialTagType(row.pipeMaterial)" size="small">{{ row.pipeMaterial || '-' }}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="管径(mm)" align="center" prop="pipeDiameter" width="100" />
+      <el-table-column label="长度(m)" align="center" prop="pipeLength" width="100" />
+      <el-table-column label="起点位置" align="center" prop="startPoint" :show-overflow-tooltip="true" min-width="140" />
+      <el-table-column label="终点位置" align="center" prop="endPoint" :show-overflow-tooltip="true" min-width="140" />
+      <el-table-column label="铺设年份" align="center" prop="layingYear" width="100" />
+      <el-table-column label="设计压力(MPa)" align="center" prop="pressureRating" width="130" />
+      <el-table-column label="状态" align="center" width="80">
+        <template #default="{ row }">
+          <el-tag 
+            :type="row.status == 1 ? 'success' : 'danger'" 
+            size="small"
+          >
+            {{ row.status == 1 ? '正常' : '停用' }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160" />
+      <el-table-column label="操作" align="center" width="180" fixed="right">
+        <template #default="{ row }">
+          <el-button size="small" type="text" icon="View" @click="handleDetail(row)">详情</el-button>
+          <el-button size="small" type="text" icon="Edit" @click="handleUpdate(row)" v-hasPermi="['waterSupply:pipeInfo:edit']">修改</el-button>
+          <el-button size="small" type="text" icon="Delete" @click="handleDelete(row)" v-hasPermi="['waterSupply:pipeInfo:remove']">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 分页 -->
+    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+
+    <!-- 新增/修改对话框 -->
+    <el-dialog :title="dialogTitle" v-model="dialogVisible" width="700px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="管网编号" prop="pipeCode">
+              <el-input v-model="form.pipeCode" placeholder="请输入管网编号" maxlength="50" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="管网名称" prop="pipeName">
+              <el-input v-model="form.pipeName" placeholder="请输入管网名称" maxlength="100" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="管道材质" prop="pipeMaterial">
+              <el-select v-model="form.pipeMaterial" placeholder="请选择管道材质" style="width: 100%">
+                <el-option label="铸铁" value="铸铁" />
+                <el-option label="PE" value="PE" />
+                <el-option label="钢管" value="钢管" />
+                <el-option label="球墨铸铁" value="球墨铸铁" />
+                <el-option label="PVC" value="PVC" />
+                <el-option label="混凝土" value="混凝土" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="管径(mm)" prop="pipeDiameter">
+              <el-input-number v-model="form.pipeDiameter" :min="0" :precision="0" style="width: 100%" placeholder="请输入管径" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="管道长度(m)" prop="pipeLength">
+              <el-input-number v-model="form.pipeLength" :min="0" :precision="2" style="width: 100%" placeholder="请输入管道长度" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="铺设年份" prop="layingYear">
+              <el-date-picker v-model="form.layingYear" type="year" placeholder="请选择铺设年份" value-format="YYYY" style="width: 100%" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="设计压力(MPa)" prop="pressureRating">
+              <el-input-number v-model="form.pressureRating" :min="0" :precision="2" style="width: 100%" placeholder="请输入设计压力" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="运行状态" prop="status">
+              <el-radio-group v-model="form.status">
+                <el-radio v-for="dict in sysNormalDisable" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="起点位置" prop="startPoint">
+              <el-input v-model="form.startPoint" placeholder="请输入起点位置" maxlength="200" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="终点位置" prop="endPoint">
+              <el-input v-model="form.endPoint" placeholder="请输入终点位置" maxlength="200" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="备注" prop="remark">
+              <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入备注" maxlength="500" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <template #footer>
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="dialogVisible = false">取 消</el-button>
+      </template>
+    </el-dialog>
+
+    <!-- 详情对话框 -->
+    <el-dialog title="管网详情" v-model="detailVisible" width="600px" append-to-body>
+      <el-descriptions :column="2" border>
+        <el-descriptions-item label="管网编号">{{ detailData.pipeCode }}</el-descriptions-item>
+        <el-descriptions-item label="管网名称">{{ detailData.pipeName }}</el-descriptions-item>
+        <el-descriptions-item label="管道材质">{{ detailData.pipeMaterial }}</el-descriptions-item>
+        <el-descriptions-item label="管径(mm)">{{ detailData.pipeDiameter }}</el-descriptions-item>
+        <el-descriptions-item label="管道长度(m)">{{ detailData.pipeLength }}</el-descriptions-item>
+        <el-descriptions-item label="铺设年份">{{ detailData.layingYear }}</el-descriptions-item>
+        <el-descriptions-item label="设计压力(MPa)">{{ detailData.pressureRating }}</el-descriptions-item>
+        <el-descriptions-item label="运行状态">
+          <el-tag :type="detailData.status === '0' ? 'success' : 'danger'" size="small">
+            {{ detailData.status === '0' ? '正常' : '停用' }}
+          </el-tag>
+        </el-descriptions-item>
+        <el-descriptions-item label="起点位置" :span="2">{{ detailData.startPoint }}</el-descriptions-item>
+        <el-descriptions-item label="终点位置" :span="2">{{ detailData.endPoint }}</el-descriptions-item>
+        <el-descriptions-item label="备注" :span="2">{{ detailData.remark }}</el-descriptions-item>
+        <el-descriptions-item label="创建者">{{ detailData.createBy }}</el-descriptions-item>
+        <el-descriptions-item label="创建时间">{{ detailData.createTime }}</el-descriptions-item>
+        <el-descriptions-item label="更新者">{{ detailData.updateBy }}</el-descriptions-item>
+        <el-descriptions-item label="更新时间">{{ detailData.updateTime }}</el-descriptions-item>
+      </el-descriptions>
+      <template #footer>
+        <el-button @click="detailVisible = false">关 闭</el-button>
+      </template>
+    </el-dialog>
+
+    <!-- 回收站对话框 -->
+    <el-dialog title="回收站" v-model:visible="recycleVisible" width="900px" append-to-body>
+      <el-form :model="recycleQuery" ref="recycleForm" :inline="true" size="small">
+        <el-form-item label="管网编号" prop="pipeCode">
+          <el-input v-model="recycleQuery.pipeCode" placeholder="请输入编号" clearable />
+        </el-form-item>
+        <el-form-item label="管网名称" prop="pipeName">
+          <el-input v-model="recycleQuery.pipeName" placeholder="请输入名称" clearable />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" icon="Search" @click="getRecycleList">搜索</el-button>
+          <el-button icon="Refresh" @click="resetRecycleQuery">重置</el-button>
+        </el-form-item>
+      </el-form>
+      <el-table v-loading="recycleLoading" :data="recycleData" @selection-change="handleRecycleSelectionChange">
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column label="管网编号" align="center" prop="pipeCode" />
+        <el-table-column label="管网名称" align="center" prop="pipeName" />
+        <el-table-column label="管道材质" align="center" prop="pipeMaterial" width="100" />
+        <el-table-column label="管径(mm)" align="center" prop="pipeDiameter" width="100" />
+        <el-table-column label="长度(m)" align="center" prop="pipeLength" width="100" />
+        <el-table-column label="状态" align="center" width="80">
+          <template #default="{ row }">
+            <dict-tag :options="sysNormalDisable" :value="row.status" />
+          </template>
+        </el-table-column>
+        <el-table-column label="删除时间" align="center" prop="updateTime" width="160" />
+        <el-table-column label="操作" align="center" width="150">
+          <template #default="{ row }">
+            <el-button size="small" type="text" icon="RefreshLeft" @click="handleRestore(row)">恢复</el-button>
+            <el-button size="small" type="text" icon="Delete" @click="handleDeletePhysically(row)">
+              <span style="color: #F56C6C">彻底删除</span>
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination v-show="recycleTotal > 0" :total="recycleTotal" v-model:page="recycleQuery.pageNum" v-model:limit="recycleQuery.pageSize" @pagination="getRecycleList" />
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listPipeInfo, getPipeInfo, addPipeInfo, updatePipeInfo, delPipeInfo, listRecyclePipeInfo, restorePipeInfo, deletePhysicallyPipeInfo } from '@/api/pipeNetwork/pipeInfo'
+import { getDicts } from '@/api/system/dict/data'
+
+export default {
+  name: 'WaterPipeInfo',
+  data() {
+    return {
+
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 表格数据
+      tableData: [],
+      // 日期范围
+      dateRange: [],
+      // 弹出层标题
+      dialogTitle: '',
+      // 是否显示弹出层
+      dialogVisible: false,
+      // 详情显示
+      detailVisible: false,
+      // 详情数据
+      detailData: {},
+      // 回收站显示
+      recycleVisible: false,
+      // 回收站加载
+      recycleLoading: false,
+      // 回收站数据
+      recycleData: [],
+      // 回收站总条数
+      recycleTotal: 0,
+      // 回收站选中数组
+      recycleIds: [],
+      // 系统状态字典
+      sysNormalDisable: [ 
+        { value: 1, label: '正常' },
+        { value: 0, label: '停用' }
+      ],
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        pipeCode: undefined,
+        pipeName: undefined,
+        pipeMaterial: undefined,
+        status: undefined
+      },
+      // 回收站查询参数
+      recycleQuery: {
+        pageNum: 1,
+        pageSize: 10,
+        pipeCode: undefined,
+        pipeName: undefined
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        pipeCode: [
+          { required: true, message: '管网编号不能为空', trigger: 'blur' }
+        ],
+        pipeName: [
+          { required: true, message: '管网名称不能为空', trigger: 'blur' }
+        ],
+        pipeMaterial: [
+          { required: true, message: '请选择管道材质', trigger: 'change' }
+        ]
+      }
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    /** 查询管网信息列表 */
+    getList() {
+      this.loading = true
+      listPipeInfo(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+        this.tableData = response.data.records
+        this.total = response.data.total
+        this.loading = false
+        console.log("入参线信息列表",this.queryParams)
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+    /** 管道材质标签类型 */
+    materialTagType(material) {
+      const map = { '铸铁': '', 'PE': 'success', '钢管': 'warning', '球墨铸铁': 'info', 'PVC': 'danger', '混凝土': '' }
+      return map[material] || ''
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1
+      this.getList()
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.dateRange = []
+      this.resetForm('queryForm')
+      this.handleQuery()
+    },
+    /** 多选框选中数据 */
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length !== 1
+      this.multiple = !selection.length
+    },
+    /** 回收站多选框选中 */
+    handleRecycleSelectionChange(selection) {
+      this.recycleIds = selection.map(item => item.id)
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset()
+      this.dialogTitle = '新增管网信息'
+      this.dialogVisible = true
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset()
+      const id = row.id || this.ids
+      getPipeInfo(id).then(response => {
+        this.form = response.data
+        this.dialogTitle = '修改管网信息'
+        this.dialogVisible = true
+      })
+    },
+    /** 详情按钮操作 */
+    handleDetail(row) {
+      getPipeInfo(row.id).then(response => {
+        this.detailData = response.data
+        this.detailVisible = true
+      })
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          if (this.form.id != undefined) {
+            updatePipeInfo(this.form).then(() => {
+              this.$modal.msgSuccess('修改成功')
+              this.dialogVisible = false
+              this.getList()
+            })
+          } else {
+            addPipeInfo(this.form).then(() => {
+              this.$modal.msgSuccess('新增成功')
+              this.dialogVisible = false
+              this.getList()
+            })
+          }
+        }
+      })
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id ? [row.id] : this.ids
+      this.$modal.confirm('是否确认删除管网编号为"' + ids.join(',') + '"的数据项?').then(() => {
+        return delPipeInfo(ids.join(','))
+      }).then(() => {
+        this.getList()
+        this.$modal.msgSuccess('删除成功')
+      }).catch(() => {})
+    },
+    /** 打开回收站 */
+    handleRecycle() {
+      this.recycleVisible = true
+      this.getRecycleList()
+    },
+    /** 查询回收站列表 */
+    getRecycleList() {
+      this.recycleLoading = true
+      listRecyclePipeInfo(this.recycleQuery).then(response => {
+        this.recycleData = response.data.records
+        this.recycleTotal = response.data.total
+        this.recycleLoading = false
+      }).catch(() => {
+        this.recycleLoading = false
+      })
+    },
+    /** 回收站搜索重置 */
+    resetRecycleQuery() {
+      this.resetForm('recycleForm')
+      this.getRecycleList()
+    },
+    /** 恢复数据 */
+    handleRestore(row) {
+      const ids = row.id || this.recycleIds
+      this.$modal.confirm('是否确认恢复该数据?').then(() => {
+        return restorePipeInfo(Array.isArray(ids) ? ids.join(',') : ids)
+      }).then(() => {
+        this.getRecycleList()
+        this.getList()
+        this.$modal.msgSuccess('恢复成功')
+      }).catch(() => {})
+    },
+    /** 彻底删除 */
+    handleDeletePhysically(row) {
+      const ids = row.id || this.recycleIds
+      this.$modal.confirm('彻底删除后数据不可恢复,是否继续?').then(() => {
+        return deletePhysicallyPipeInfo(Array.isArray(ids) ? ids.join(',') : ids)
+      }).then(() => {
+        this.getRecycleList()
+        this.$modal.msgSuccess('彻底删除成功')
+      }).catch(() => {})
+    },
+    /** 表单重置 */
+    reset() {
+      this.form = {
+        status: '0'
+      }
+      this.resetForm('form')
+    }
+  }
+}
+</script>

+ 408 - 0
src/views/subSystem/basic/pumpStation/index.vue

@@ -0,0 +1,408 @@
+<template>
+  <div class="app-container">
+    <!-- 搜索区域 -->
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="80px">
+      <el-form-item label="泵站编号" prop="stationCode">
+        <el-input v-model="queryParams.stationCode" placeholder="请输入泵站编号" clearable size="small" @keyup.enter="handleQuery" />
+      </el-form-item>
+      <el-form-item label="泵站名称" prop="stationName">
+        <el-input v-model="queryParams.stationName" placeholder="请输入泵站名称" clearable size="small" @keyup.enter="handleQuery" />
+      </el-form-item>
+      <el-form-item label="运行状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small" style="width: 120px">
+          <el-option label="正常" value="0" />
+          <el-option label="故障停运" value="1" />
+          <el-option label="检修中" value="2" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="负责人" prop="principal">
+        <el-input v-model="queryParams.principal" placeholder="请输入负责人" clearable size="small" @keyup.enter="handleQuery" />
+      </el-form-item>
+      <el-form-item label="创建时间">
+        <el-date-picker
+          v-model="dateRange"
+          size="small"
+          style="width: 240px"
+          value-format="YYYY-MM-DD HH:mm:ss"
+          type="datetimerange"
+          range-separator="-"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="Search" size="small" @click="handleQuery">搜索</el-button>
+        <el-button icon="Refresh" size="small" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- 操作按钮区域 -->
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button type="primary" plain icon="Plus" size="small" @click="handleAdd" v-hasPermi="['waterSupply:pumpStation:add']">新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="Delete" size="small" :disabled="multiple" @click="handleDelete" v-hasPermi="['waterSupply:pumpStation:remove']">删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button type="warning" plain icon="Delete" size="small" @click="handleRecycle" v-hasPermi="['waterSupply:pumpStation:remove']">回收站</el-button>
+      </el-col>
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
+    </el-row>
+
+    <!-- 数据表格 -->
+    <el-table v-loading="loading" :data="tableData" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="泵站编号" align="center" prop="stationCode" :show-overflow-tooltip="true" min-width="120" />
+      <el-table-column label="泵站名称" align="center" prop="stationName" :show-overflow-tooltip="true" min-width="140" />
+      <el-table-column label="泵站地址" align="center" prop="location" :show-overflow-tooltip="true" min-width="160" />
+      <el-table-column label="水泵数量" align="center" prop="pumpCount" width="90" />
+      <el-table-column label="设计流量(m³/h)" align="center" prop="designFlow" width="130" />
+      <el-table-column label="设计扬程(m)" align="center" prop="designHead" width="110" />
+      <el-table-column label="装机容量(kW)" align="center" prop="powerCapacity" width="120" />
+      <el-table-column label="投运日期" align="center" prop="commissionDate" width="110" />
+      <el-table-column label="运行状态" align="center" width="100">
+        <template #default="{ row }">
+          <el-tag :type="statusTagType(row.status)" size="small">{{ statusLabel(row.status) }}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="负责人" align="center" prop="principal" width="100" />
+      <el-table-column label="联系电话" align="center" prop="contactPhone" width="120" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="160" />
+      <el-table-column label="操作" align="center" width="180" fixed="right">
+        <template #default="{ row }">
+          <el-button size="small" type="text" icon="View" @click="handleDetail(row)">详情</el-button>
+          <el-button size="small" type="text" icon="Edit" @click="handleUpdate(row)" v-hasPermi="['waterSupply:pumpStation:edit']">修改</el-button>
+          <el-button size="small" type="text" icon="Delete" @click="handleDelete(row)" v-hasPermi="['waterSupply:pumpStation:remove']">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 分页 -->
+    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+
+    <!-- 新增/修改对话框 -->
+    <el-dialog :title="dialogTitle" v-model="dialogVisible" width="750px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="110px">
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="泵站编号" prop="stationCode">
+              <el-input v-model="form.stationCode" placeholder="请输入泵站编号" maxlength="50" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="泵站名称" prop="stationName">
+              <el-input v-model="form.stationName" placeholder="请输入泵站名称" maxlength="100" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="泵站地址" prop="location">
+              <el-input v-model="form.location" placeholder="请输入泵站地址" maxlength="200" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="水泵数量" prop="pumpCount">
+              <el-input-number v-model="form.pumpCount" :min="0" :precision="0" style="width: 100%" placeholder="请输入水泵数量" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="设计流量(m³/h)" prop="designFlow">
+              <el-input-number v-model="form.designFlow" :min="0" :precision="2" style="width: 100%" placeholder="请输入设计流量" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="设计扬程(m)" prop="designHead">
+              <el-input-number v-model="form.designHead" :min="0" :precision="2" style="width: 100%" placeholder="请输入设计扬程" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="装机容量(kW)" prop="powerCapacity">
+              <el-input-number v-model="form.powerCapacity" :min="0" :precision="2" style="width: 100%" placeholder="请输入装机容量" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="投运日期" prop="commissionDate">
+              <el-date-picker v-model="form.commissionDate" type="date" placeholder="请选择投运日期" value-format="YYYY-MM-DD" style="width: 100%" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="运行状态" prop="status">
+              <el-radio-group v-model="form.status">
+                <el-radio label="0">正常</el-radio>
+                <el-radio label="1">故障停运</el-radio>
+                <el-radio label="2">检修中</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="负责人" prop="principal">
+              <el-input v-model="form.principal" placeholder="请输入负责人" maxlength="50" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="联系电话" prop="contactPhone">
+              <el-input v-model="form.contactPhone" placeholder="请输入联系电话" maxlength="20" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="24">
+            <el-form-item label="备注" prop="remark">
+              <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入备注" maxlength="500" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <template #footer>
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="dialogVisible = false">取 消</el-button>
+      </template>
+    </el-dialog>
+
+    <!-- 详情对话框 -->
+    <el-dialog title="泵站详情" v-model="detailVisible" width="650px" append-to-body>
+      <el-descriptions :column="2" border>
+        <el-descriptions-item label="泵站编号">{{ detailData.stationCode }}</el-descriptions-item>
+        <el-descriptions-item label="泵站名称">{{ detailData.stationName }}</el-descriptions-item>
+        <el-descriptions-item label="泵站地址" :span="2">{{ detailData.location }}</el-descriptions-item>
+        <el-descriptions-item label="水泵数量">{{ detailData.pumpCount }}</el-descriptions-item>
+        <el-descriptions-item label="设计流量(m³/h)">{{ detailData.designFlow }}</el-descriptions-item>
+        <el-descriptions-item label="设计扬程(m)">{{ detailData.designHead }}</el-descriptions-item>
+        <el-descriptions-item label="装机容量(kW)">{{ detailData.powerCapacity }}</el-descriptions-item>
+        <el-descriptions-item label="投运日期">{{ detailData.commissionDate }}</el-descriptions-item>
+        <el-descriptions-item label="运行状态">
+          <el-tag :type="statusTagType(detailData.status)" size="small">{{ statusLabel(detailData.status) }}</el-tag>
+        </el-descriptions-item>
+        <el-descriptions-item label="负责人">{{ detailData.principal }}</el-descriptions-item>
+        <el-descriptions-item label="联系电话">{{ detailData.contactPhone }}</el-descriptions-item>
+        <el-descriptions-item label="备注" :span="2">{{ detailData.remark }}</el-descriptions-item>
+        <el-descriptions-item label="创建者">{{ detailData.createBy }}</el-descriptions-item>
+        <el-descriptions-item label="创建时间">{{ detailData.createTime }}</el-descriptions-item>
+        <el-descriptions-item label="更新者">{{ detailData.updateBy }}</el-descriptions-item>
+        <el-descriptions-item label="更新时间">{{ detailData.updateTime }}</el-descriptions-item>
+      </el-descriptions>
+      <template #footer>
+        <el-button @click="detailVisible = false">关 闭</el-button>
+      </template>
+    </el-dialog>
+
+    <!-- 回收站对话框 -->
+    <el-dialog title="回收站" v-model="recycleVisible" width="900px" append-to-body>
+      <el-form :model="recycleQuery" ref="recycleForm" :inline="true" size="small">
+        <el-form-item label="泵站编号" prop="stationCode">
+          <el-input v-model="recycleQuery.stationCode" placeholder="请输入编号" clearable />
+        </el-form-item>
+        <el-form-item label="泵站名称" prop="stationName">
+          <el-input v-model="recycleQuery.stationName" placeholder="请输入名称" clearable />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" icon="Search" @click="getRecycleList">搜索</el-button>
+          <el-button icon="Refresh" @click="resetRecycleQuery">重置</el-button>
+        </el-form-item>
+      </el-form>
+      <el-table v-loading="recycleLoading" :data="recycleData" @selection-change="handleRecycleSelectionChange">
+        <el-table-column type="selection" width="55" align="center" />
+        <el-table-column label="泵站编号" align="center" prop="stationCode" />
+        <el-table-column label="泵站名称" align="center" prop="stationName" />
+        <el-table-column label="泵站地址" align="center" prop="location" :show-overflow-tooltip="true" />
+        <el-table-column label="负责人" align="center" prop="principal" width="100" />
+        <el-table-column label="运行状态" align="center" width="100">
+          <template #default="{ row }">
+            <el-tag :type="statusTagType(row.status)" size="small">{{ statusLabel(row.status) }}</el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column label="删除时间" align="center" prop="updateTime" width="160" />
+        <el-table-column label="操作" align="center" width="150">
+          <template #default="{ row }">
+            <el-button size="small" type="text" icon="RefreshLeft" @click="handleRestore(row)">恢复</el-button>
+            <el-button size="small" type="text" icon="Delete" @click="handleDeletePhysically(row)">
+              <span style="color: #F56C6C">彻底删除</span>
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination v-show="recycleTotal > 0" :total="recycleTotal" v-model:page="recycleQuery.pageNum" v-model:limit="recycleQuery.pageSize" @pagination="getRecycleList" />
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listPumpStation, getPumpStation, addPumpStation, updatePumpStation, delPumpStation, listRecyclePumpStation, restorePumpStation, deletePhysicallyPumpStation } from '@/api/pipeNetwork/waterPumpStation'
+
+export default {
+  name: 'WaterPumpStation',
+  data() {
+    return {
+      loading: true,
+      ids: [],
+      single: true,
+      multiple: true,
+      showSearch: true,
+      total: 0,
+      tableData: [],
+      dateRange: [],
+      dialogTitle: '',
+      dialogVisible: false,
+      detailVisible: false,
+      detailData: {},
+      recycleVisible: false,
+      recycleLoading: false,
+      recycleData: [],
+      recycleTotal: 0,
+      recycleIds: [],
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        stationCode: undefined,
+        stationName: undefined,
+        status: undefined,
+        principal: undefined
+      },
+      recycleQuery: {
+        pageNum: 1,
+        pageSize: 10,
+        stationCode: undefined,
+        stationName: undefined
+      },
+      form: {},
+      rules: {
+        stationCode: [
+          { required: true, message: '泵站编号不能为空', trigger: 'blur' }
+        ],
+        stationName: [
+          { required: true, message: '泵站名称不能为空', trigger: 'blur' }
+        ]
+      }
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    getList() {
+      this.loading = true
+      listPumpStation(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
+        this.tableData = response.data.records
+        this.total = response.data.total
+        this.loading = false
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+    statusTagType(status) {
+      const map = { '0': 'success', '1': 'danger', '2': 'warning' }
+      return map[status] || 'info'
+    },
+    statusLabel(status) {
+      const map = { '0': '正常', '1': '故障停运', '2': '检修中' }
+      return map[status] || '未知'
+    },
+    handleQuery() {
+      this.queryParams.pageNum = 1
+      this.getList()
+    },
+    resetQuery() {
+      this.dateRange = []
+      this.resetForm('queryForm')
+      this.handleQuery()
+    },
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length !== 1
+      this.multiple = !selection.length
+    },
+    handleRecycleSelectionChange(selection) {
+      this.recycleIds = selection.map(item => item.id)
+    },
+    handleAdd() {
+      this.reset()
+      this.dialogTitle = '新增泵站信息'
+      this.dialogVisible = true
+    },
+    handleUpdate(row) {
+      this.reset()
+      const id = row.id || this.ids
+      getPumpStation(id).then(response => {
+        this.form = response.data
+        this.dialogTitle = '修改泵站信息'
+        this.dialogVisible = true
+      })
+    },
+    handleDetail(row) {
+      getPumpStation(row.id).then(response => {
+        this.detailData = response.data
+        this.detailVisible = true
+      })
+    },
+    submitForm() {
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          if (this.form.id != undefined) {
+            updatePumpStation(this.form).then(() => {
+              this.$modal.msgSuccess('修改成功')
+              this.dialogVisible = false
+              this.getList()
+            })
+          } else {
+            addPumpStation(this.form).then(() => {
+              this.$modal.msgSuccess('新增成功')
+              this.dialogVisible = false
+              this.getList()
+            })
+          }
+        }
+      })
+    },
+    handleDelete(row) {
+      const ids = row.id ? [row.id] : this.ids
+      this.$modal.confirm('是否确认删除泵站编号为"' + ids.join(',') + '"的数据项?').then(() => {
+        return delPumpStation(ids.join(','))
+      }).then(() => {
+        this.getList()
+        this.$modal.msgSuccess('删除成功')
+      }).catch(() => {})
+    },
+    handleRecycle() {
+      this.recycleVisible = true
+      this.getRecycleList()
+    },
+    getRecycleList() {
+      this.recycleLoading = true
+      listRecyclePumpStation(this.recycleQuery).then(response => {
+        this.recycleData = response.data.records
+        this.recycleTotal = response.data.total
+        this.recycleLoading = false
+      }).catch(() => {
+        this.recycleLoading = false
+      })
+    },
+    resetRecycleQuery() {
+      this.resetForm('recycleForm')
+      this.getRecycleList()
+    },
+    handleRestore(row) {
+      const ids = row.id || this.recycleIds
+      this.$modal.confirm('是否确认恢复该数据?').then(() => {
+        return restorePumpStation(Array.isArray(ids) ? ids.join(',') : ids)
+      }).then(() => {
+        this.getRecycleList()
+        this.getList()
+        this.$modal.msgSuccess('恢复成功')
+      }).catch(() => {})
+    },
+    handleDeletePhysically(row) {
+      const ids = row.id || this.recycleIds
+      this.$modal.confirm('彻底删除后数据不可恢复,是否继续?').then(() => {
+        return deletePhysicallyPumpStation(Array.isArray(ids) ? ids.join(',') : ids)
+      }).then(() => {
+        this.getRecycleList()
+        this.$modal.msgSuccess('彻底删除成功')
+      }).catch(() => {})
+    },
+    reset() {
+      this.form = {
+        status: '0'
+      }
+      this.resetForm('form')
+    }
+  }
+}
+</script>

+ 2 - 1
vite.config.js

@@ -31,7 +31,8 @@ export default defineConfig(({ mode, command }) => {
       proxy: {
         '/dev-api': {
           // target: 'http://192.168.110.235:8300/pipe',
-          target: 'http://111.23.174.45:8301',
+          target: 'http://127.0.0.1:8300/pipe',
+          // target: 'http://111.23.174.45:8301',
           changeOrigin: true,
           rewrite: (p) => p.replace(/^\/dev-api/, '')
         }

+ 253 - 0
项目文件夹描述.md

@@ -0,0 +1,253 @@
+# 城市生命线 — 项目目录结构说明
+
+```
+city-life-line/                      # 城市生命线 — 地下管网管控平台
+├── 📄 .env.development              # 开发环境变量(端口代理、API地址等)
+├── 📄 .env.production               # 生产环境变量
+├── 📄 .env.staging                  # 预发布环境变量
+├── 📄 .gitignore                    # Git 忽略规则
+├── 📁 .idea/                        # JetBrains IDE 配置(自动生成)
+├── 📁 .vscode/                      # VSCode 编辑器配置
+├── 📄 index.html                    # 应用入口 HTML 文件
+├── 📄 LICENSE                       # MIT 开源许可证
+├── 📄 README.md                     # 项目说明文档
+├── 📄 package.json                  # 项目依赖 & 脚本定义
+├── 📄 package-lock.json             # 依赖版本锁定文件
+├── 📄 uno.config.js                 # UnoCSS 原子化 CSS 配置
+├── 📄 vite.config.js                # Vite 构建配置(代理、别名、端口等)
+│
+├── 📁 bin/                          # 构建/打包/运行脚本
+│   ├── build.bat                    # 构建命令
+│   ├── package.bat                  # 打包命令
+│   └── run-web.bat                  # 一键启动 Web 服务
+│
+├── 📁 html/                         # 静态 HTML 资源
+│   └── ie.html                      # IE 浏览器兼容提示页
+│
+├── 📁 public/                       # 静态资源(直接复制到输出目录)
+│   ├── favicon.ico                  # 网站图标
+│   └── logo.png                     # Logo 图片
+│
+├── 📁 vite/                         # Vite 插件配置
+│   └── plugins/                     # 自定义 Vite 插件代码
+│
+└── 📁 src/                          # 源代码主目录 ⭐
+    ├── 📄 App.vue                   # Vue 根组件
+    ├── 📄 main.js                   # 应用入口(挂载 Vue、注册插件/指令)
+    ├── 📄 permission.js             # 路由权限守卫(登录拦截、动态路由)
+    ├── 📄 settings.js               # 全局设置参数
+    │
+    ├── 📁 api/                      # 接口层(按模块拆分)
+    │   ├── login.js                 # 登录/注册/验证码接口
+    │   ├── menu.js                  # 菜单接口
+    │   ├── dispatch.js              # 应急调度模块接口
+    │   ├── drainage.js              # 排水系统模块接口
+    │   ├── monitor/                 # 监控管理接口
+    │   │   ├── cache.js             # 缓存监控
+    │   │   ├── job.js               # 定时任务
+    │   │   ├── jobLog.js            # 任务日志
+    │   │   ├── logininfor.js        # 登录日志
+    │   │   ├── online.js            # 在线用户
+    │   │   ├── operlog.js           # 操作日志
+    │   │   └── server.js            # 服务器监控
+    │   ├── pipeNetwork/             # 管网模块接口
+    │   │   ├── basic.js             # 管网基础数据
+    │   │   ├── gasMonitor.js        # 燃气监测
+    │   │   ├── hazard.js            # 隐患管理
+    │   │   └── pdeviceInform.js     # 设备信息
+    │   ├── smxyjldczxt/             # 应急指挥系统接口
+    │   │   └── yjxxfb/
+    │   │       ├── dbyj.js          # 待办预警
+    │   │       └── yjfb.js          # 预警发布
+    │   ├── system/                  # 系统管理接口
+    │   │   ├── config.js            # 参数配置
+    │   │   ├── dept.js              # 部门管理
+    │   │   ├── dict/                # 字典管理
+    │   │   │   ├── data.js          # 字典数据
+    │   │   │   └── type.js          # 字典类型
+    │   │   ├── menu.js              # 菜单管理
+    │   │   ├── notice.js            # 公告管理
+    │   │   ├── post.js              # 岗位管理
+    │   │   ├── role.js              # 角色管理
+    │   │   └── user.js              # 用户管理
+    │   ├── tool/                    # 代码生成工具接口
+    │   │   └── gen.js
+    │   └── work/                    # 工单接口
+    │       └── order.js
+    │
+    ├── 📁 assets/                   # 静态资源(会经 Vite 编译处理)
+    │   ├── 401_images/              # 401 无权限页插图
+    │   ├── 404_images/              # 404 页面插图
+    │   ├── icons/svg/               # SVG 图标(通过 SvgIcon 组件使用)
+    │   ├── images/                  # 通用图片(含登录背景图)
+    │   ├── logo/                    # Logo 资源
+    │   ├── portal/                  # 门户大屏资源
+    │   └── styles/                  # 全局样式
+    │       ├── index.scss           # 样式入口(汇总引入)
+    │       ├── variables.module.scss # SCSS 变量
+    │       ├── mixin.scss           # SCSS 混入
+    │       ├── transition.scss      # 过渡动画样式
+    │       ├── element-ui.scss      # Element Plus 覆盖样式
+    │       └── sidebar.scss         # 侧边栏样式
+    │
+    ├── 📁 components/               # 公共组件
+    │   ├── Breadcrumb/              # 面包屑导航
+    │   ├── Crontab/                 # Cron 表达式配置器(年/月/周/日/时/分/秒)
+    │   ├── DictTag/                 # 字典标签
+    │   ├── Editor/                  # 富文本编辑器(Quill)
+    │   ├── FileUpload/              # 文件上传
+    │   ├── Hamburger/               # 汉堡菜单(侧边栏折叠)
+    │   ├── HeaderSearch/            # 头部搜索
+    │   ├── IconSelect/              # 图标选择器
+    │   ├── ImagePreview/            # 图片预览
+    │   ├── ImageUpload/             # 图片上传
+    │   ├── Pagination/              # 分页组件
+    │   ├── ParentView/              # 父级视图容器
+    │   ├── RightToolbar/            # 右侧工具栏
+    │   ├── RuoYi/                   # 若依框架辅助(文档/代码仓库链接)
+    │   ├── Screenfull/              # 全屏切换
+    │   ├── SizeSelect/              # 字号选择
+    │   ├── SvgIcon/                 # SVG 图标组件
+    │   ├── TopNav/                  # 顶部导航
+    │   ├── TreeSelect/              # 树形选择器
+    │   └── iFrame/                  # 内嵌 iframe 组件
+    │
+    ├── 📁 directive/                # 自定义指令
+    │   ├── index.js                 # 指令注册入口
+    │   ├── common/copyText.js       # v-copyText:一键复制文本
+    │   └── permission/              # 权限指令
+    │       ├── hasPermi.js          # v-hasPermi:按钮级权限控制
+    │       └── hasRole.js           # v-hasRole:角色级权限控制
+    │
+    ├── 📁 layout/                   # 布局组件
+    │   ├── index.vue                # 布局主框架
+    │   └── components/
+    │       ├── AppMain.vue          # 主内容区
+    │       ├── Navbar.vue           # 顶部导航栏
+    │       ├── Settings/            # 布局设置面板(主题/固定头部等)
+    │       ├── Sidebar/             # 侧边栏菜单
+    │       │   ├── index.vue        # 侧边栏主体
+    │       │   ├── Logo.vue         # 侧边栏 Logo
+    │       │   ├── Link.vue         # 外链菜单项
+    │       │   └── SidebarItem.vue  # 菜单项组件
+    │       ├── TagsView/            # 标签页视图
+    │       ├── IframeToggle/        # iframe 切换
+    │       └── InnerLink/           # 内部链接
+    │
+    ├── 📁 plugins/                  # 工具插件
+    │   ├── index.js                 # 插件注册入口
+    │   ├── auth.js                  # 权限认证辅助
+    │   ├── cache.js                 # 前端缓存(sessionStorage/localStorage)
+    │   ├── download.js              # 文件下载
+    │   ├── modal.js                 # 模态框封装
+    │   └── tab.js                   # 标签页操作
+    │
+    ├── 📁 router/                   # 路由配置
+    │   └── index.js                 # 路由定义(公共路由 + 动态路由)
+    │
+    ├── 📁 store/                    # Pinia 状态管理
+    │   ├── index.js                 # Store 注册入口
+    │   └── modules/
+    │       ├── app.js               # 应用全局状态(侧边栏/设备/尺寸)
+    │       ├── dict.js              # 字典缓存状态
+    │       ├── permission.js        # 权限菜单状态
+    │       ├── settings.js          # 布局设置状态
+    │       ├── tagsView.js          # 标签页状态
+    │       └── user.js              # 用户信息/登录/token 状态
+    │
+    ├── 📁 utils/                    # 工具函数
+    │   ├── index.js                 # 通用工具函数
+    │   ├── auth.js                  # Token 存取操作
+    │   ├── request.js               # Axios 封装(拦截器/防重复提交)
+    │   ├── coordTransform.js        # 坐标系转换工具
+    │   ├── dict.js                  # 字典翻译工具
+    │   ├── dynamicTitle.js          # 动态页面标题
+    │   └── errorCode.js             # HTTP 错误码映射
+    │
+    └── 📁 views/                    # 页面视图
+        ├── index.vue                # 系统首页(仪表盘)
+        ├── login.vue                # 登录页
+        ├── register.vue             # 注册页
+        ├── error/                   # 错误页面
+        │   ├── 401.vue              # 401 无权限
+        │   └── 404.vue              # 404 页面不存在
+        ├── redirect/                # 重定向中转页
+        │   └── index.vue
+        ├── portal/                  # 门户大屏首页
+        │   └── index.vue
+        ├── monitor/                 # 监控管理
+        │   ├── cache/               # 缓存监控
+        │   ├── druid/               # 数据库连接池监控
+        │   ├── job/                 # 定时任务管理
+        │   ├── logininfor/          # 登录日志
+        │   ├── online/              # 在线用户
+        │   ├── operlog/             # 操作日志
+        │   └── server/              # 服务器状态监控
+        ├── system/                  # 系统管理(用户/角色/菜单/字典/公告/部门/岗位)
+        ├── tool/                    # 代码生成工具
+        └── subSystem/               # 业务子系统 ⭐
+            ├── basic/               # 管网基础设施
+            │   ├── GisDashboard     # GIS 仪表盘总览
+            │   ├── PipeNetwork      # 管网管理
+            │   ├── PointManage      # 管点管理
+            │   ├── Manhole          # 井盖管理
+            │   ├── Equipment        # 设备管理
+            │   ├── EquipmentAbnormal # 设备异常
+            │   ├── GasPipePoint     # 燃气管点关联
+            │   ├── BusinessWorkOrder # 业务工单
+            │   └── RepairRecord     # 维修记录
+            ├── alarm/               # 告警模块
+            │   ├── AlarmList        # 告警列表
+            │   └── AlarmMap         # 告警地图
+            ├── gas/                 # 燃气管网系统
+            │   ├── gasBasicadata/   # 基础数据(管网/设备)
+            │   ├── gasfxpg/         # 风险评估
+            │   ├── gashiddendanger/ # 隐患排查
+            │   ├── gasMonitor/      # 燃气监测
+            │   ├── gasWorkOrder/    # 燃气工单
+            │   └── gasHome/         # 燃气首页
+            ├── drainage/            # 排水系统
+            │   ├── home             # 排水首页
+            │   ├── jcsj/            # 基础数据(管网/泵站/设备/检查井)
+            │   ├── jcyj/            # 监测预警(流量/液位+GIS)
+            │   ├── spjc/            # 视频监测(GIS/播放/管理)
+            │   ├── jcbj/            # 监测报警(四级处置流程)
+            │   ├── fxpg/            # 风险评估
+            │   └── DrainageWorkOrder # 排水工单
+            ├── dispatch/            # 应急指挥调度
+            │   ├── dishome          # 调度首页
+            │   ├── disOnDuty/       # 值班管理(事故/故障/监督/值班表)
+            │   ├── disPlanManage/   # 预案管理(编辑/审批/分级)
+            │   ├── disExerciseMan/  # 模拟演练(模拟/实战/课程/规划)
+            │   ├── disDecisionDep/  # 辅助决策(方案/路线/可视化)
+            │   └── disAssess/       # 总结评估(查询/分析/汇总)
+            └── cityLifeline/        # 城市生命线总览大屏
+```
+
+---
+
+## 项目概况
+
+| 项目 | 说明 |
+|------|------|
+| **框架** | Vue 3.4 + Vite 5.3 |
+| **UI 库** | Element Plus 2.7 |
+| **状态管理** | Pinia |
+| **CSS 方案** | UnoCSS(原子化)+ SCSS |
+| **地图** | Leaflet + 百度地图 WebGL |
+| **图表** | ECharts 5 |
+| **HTTP 请求** | Axios(Token 注入、防重复提交、错误统一处理) |
+| **鉴权** | JWT + 路由权限守卫 + 按钮级指令控制 |
+| **基础框架** | 基于 RuoYi-Vue 改造 |
+| **业务领域** | 城市地下管网管控(燃气/排水/供水 + 应急指挥调度) |
+
+## 子系统模块
+
+| 模块 | 路径 | 说明 |
+|------|------|------|
+| 管网基础 | `subSystem/basic/` | 管网/管点/井盖/设备管理 + GIS 仪表盘 |
+| 告警管理 | `subSystem/alarm/` | 告警列表 + GIS 地图告警 |
+| 燃气管网 | `subSystem/gas/` | 基础数据/风险评估/隐患/监测/工单 |
+| 排水系统 | `subSystem/drainage/` | 基础数据/监测预警/视频监测/报警/风险评估/工单 |
+| 应急调度 | `subSystem/dispatch/` | 值班/预案/演练/决策/评估 |
+| 生命线总览 | `subSystem/cityLifeline/` | 城市生命线大屏总览 |