全过程数据管理子系统
15
frontend-sjgl/.editorconfig
Normal file
@ -0,0 +1,15 @@
|
||||
# http://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*] # 表示所有文件适用
|
||||
charset = utf-8 # 设置文件字符集为 utf-8
|
||||
indent_style = space # 缩进风格(tab | space)
|
||||
indent_size = 2 # 缩进大小
|
||||
end_of_line = lf # 控制换行类型(lf | cr | crlf)
|
||||
trim_trailing_whitespace = true # 去除行首的任意空白字符
|
||||
insert_final_newline = true # 始终在文件末尾插入一个新行
|
||||
|
||||
[*.md] # 表示仅 md 文件适用以下规则
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
||||
22
frontend-sjgl/.env.development
Normal file
@ -0,0 +1,22 @@
|
||||
## 开发环境
|
||||
|
||||
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
|
||||
NODE_ENV='development'
|
||||
|
||||
VITE_APP_TITLE = '全过程数据管理子系统'
|
||||
VITE_APP_PORT = 5000
|
||||
VITE_APP_BASE_API = '/dev-api'
|
||||
# 本地环境
|
||||
VITE_APP_BASE_URL = 'http://localhost:8093'
|
||||
# 测试环境
|
||||
# VITE_APP_BASE_URL = 'http://172.16.21.142:8093'
|
||||
# 汤伟
|
||||
VITE_APP_BASE_URL = 'http://10.84.111.235:8093'
|
||||
# 李林
|
||||
# VITE_APP_BASE_URL = 'http://10.84.111.25:8093'
|
||||
|
||||
## 开发环境 附件服务地址
|
||||
VITE_APP_ATTACHMENT_URL = 'https://211.99.26.225:12125'
|
||||
# 地图服务地址
|
||||
VITE_APP_MAP_URL = 'https://211.99.26.225:18085'
|
||||
# ?menu=systemManageMenu&page=disposeManage
|
||||
14
frontend-sjgl/.env.production
Normal file
@ -0,0 +1,14 @@
|
||||
## 生产环境
|
||||
NODE_ENV='production'
|
||||
|
||||
VITE_APP_TITLE = 'qgc-buji-web'
|
||||
VITE_APP_PORT = 5000
|
||||
VITE_APP_BASE_API = '/prod-api'
|
||||
## 生产环境API地址
|
||||
VITE_APP_BASE_URL = 'http://localhost:8093'
|
||||
## 生产环境导入预览地址
|
||||
VITE_APP_BASE_API_URL = 'https://211.99.26.225:12130/prod-api'
|
||||
## 生产环境 附件服务地址
|
||||
VITE_APP_ATTACHMENT_URL = 'https://211.99.26.225:12125'
|
||||
# 地图服务地址
|
||||
VITE_APP_MAP_URL = 'https://211.99.26.225:18085'
|
||||
6
frontend-sjgl/.env.staging
Normal file
@ -0,0 +1,6 @@
|
||||
## 模拟环境
|
||||
NODE_ENV='staging'
|
||||
|
||||
VITE_APP_TITLE = 'qgc-buji-web'
|
||||
VITE_APP_PORT = 3000
|
||||
VITE_APP_BASE_API = '/prod--api'
|
||||
16
frontend-sjgl/.eslintignore
Normal file
@ -0,0 +1,16 @@
|
||||
*.sh
|
||||
node_modules
|
||||
*.md
|
||||
*.woff
|
||||
*.ttf
|
||||
.vscode
|
||||
.idea
|
||||
dist
|
||||
/public
|
||||
/docs
|
||||
.husky
|
||||
.local
|
||||
/bin
|
||||
.eslintrc.js
|
||||
prettier.config.js
|
||||
src/assets
|
||||
33
frontend-sjgl/.eslintrc.js
Normal file
@ -0,0 +1,33 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
node: true
|
||||
},
|
||||
globals: {
|
||||
defineProps: 'readonly',
|
||||
defineEmits: 'readonly',
|
||||
defineExpose: 'readonly',
|
||||
withDefaults: 'readonly',
|
||||
DialogType: "readonly",
|
||||
OptionType: "readonly",
|
||||
},
|
||||
parser: 'vue-eslint-parser',
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:vue/vue3-essential',
|
||||
'plugin:@typescript-eslint/recommended'
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
parser: '@typescript-eslint/parser',
|
||||
sourceType: 'module'
|
||||
},
|
||||
plugins: ['vue', '@typescript-eslint'],
|
||||
rules: {
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off', // 关闭空方法检查
|
||||
'@typescript-eslint/no-explicit-any': 'off', // 关闭any类型的警告
|
||||
'vue/no-v-model-argument': 'off'
|
||||
}
|
||||
};
|
||||
17
frontend-sjgl/.gitignore
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.local
|
||||
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
4
frontend-sjgl/.lingma/settings.local.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"permissions": {},
|
||||
"outputStyle": "Vibe"
|
||||
}
|
||||
5
frontend-sjgl/.npmrc
Normal file
@ -0,0 +1,5 @@
|
||||
registry=https://registry.npmmirror.com
|
||||
fetch-retries=5
|
||||
strict-peer-dependencies=false
|
||||
# 添加 Node.js 内存配置
|
||||
node-options=--max-old-space-size=4096
|
||||
9
frontend-sjgl/.prettierignore
Normal file
@ -0,0 +1,9 @@
|
||||
/dist/*
|
||||
.local
|
||||
.output.js
|
||||
/node_modules/**
|
||||
|
||||
**/*.svg
|
||||
**/*.sh
|
||||
|
||||
/public/*
|
||||
36
frontend-sjgl/.prettierrc.js
Normal file
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 代码格式化配置
|
||||
*/
|
||||
module.exports = {
|
||||
// 指定每个缩进级别的空格数
|
||||
tabWidth: 2,
|
||||
// 使用制表符而不是空格缩进行
|
||||
useTabs: false,
|
||||
// 在语句末尾打印分号
|
||||
semi: true,
|
||||
// 使用单引号而不是双引号
|
||||
singleQuote: true,
|
||||
// 更改引用对象属性的时间 可选值"<as-needed|consistent|preserve>"
|
||||
quoteProps: 'as-needed',
|
||||
// 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"<none|es5|all>",默认none
|
||||
trailingComma: 'none',
|
||||
// 在对象文字中的括号之间打印空格
|
||||
bracketSpacing: true,
|
||||
// 在单独的箭头函数参数周围包括括号 always:(x) => x \ avoid:x => x
|
||||
arrowParens: 'avoid',
|
||||
// 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
|
||||
rangeStart: 0,
|
||||
rangeEnd: Infinity,
|
||||
// 指定要使用的解析器,不需要写文件开头的 @prettier
|
||||
requirePragma: false,
|
||||
// 不需要自动在文件开头插入 @prettier
|
||||
insertPragma: false,
|
||||
// 换行设置 always\never\preserve
|
||||
proseWrap: 'never',
|
||||
// 指定HTML文件的全局空格敏感度 css\strict\ignore
|
||||
htmlWhitespaceSensitivity: 'css',
|
||||
// Vue文件脚本和样式标签缩进
|
||||
vueIndentScriptAndStyle: false,
|
||||
// 换行符使用 lf 结尾是 可选值"<auto|lf|crlf|cr>"
|
||||
endOfLine: 'lf',
|
||||
};
|
||||
21
frontend-sjgl/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 有来开源组织
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
26
frontend-sjgl/commitlint.config.js
Normal file
@ -0,0 +1,26 @@
|
||||
module.exports = {
|
||||
// 继承的规则
|
||||
extends: ['@commitlint/config-conventional'],
|
||||
// 定义规则类型
|
||||
rules: {
|
||||
// type 类型定义,表示 git 提交的 type 必须在以下类型范围内
|
||||
'type-enum': [
|
||||
2,
|
||||
'always',
|
||||
[
|
||||
'feat', // 新功能 feature
|
||||
'fix', // 修复 bug
|
||||
'docs', // 文档注释
|
||||
'style', // 代码格式(不影响代码运行的变动)
|
||||
'refactor', // 重构(既不增加新功能,也不是修复bug)
|
||||
'perf', // 性能优化
|
||||
'test', // 增加测试
|
||||
'chore', // 构建过程或辅助工具的变动
|
||||
'revert', // 回退
|
||||
'build' // 打包
|
||||
]
|
||||
],
|
||||
// subject 大小写不做校验
|
||||
'subject-case': [0]
|
||||
}
|
||||
};
|
||||
479
frontend-sjgl/docs/地图模块-3D Cesium实施计划.md
Normal file
@ -0,0 +1,479 @@
|
||||
# 地图模块 3D Cesium 实施计划
|
||||
|
||||
## 1. 目标
|
||||
|
||||
在现有地图体系下补齐 `3D(Cesium)` 视图能力,使其尽量复用 `2D(OpenLayers)` 的业务编排结果,满足以下要求:
|
||||
|
||||
- 3D 默认进入中国视角,不再落到美国区域。
|
||||
- 3D 初始化时显示过渡动画,再定位到中国。
|
||||
- 3D 保留基础底图加载能力,但不提供底图切换面板。
|
||||
- 3D 支持锚点展示。
|
||||
- 3D 支持与 2D 一致的鼠标悬停 popup,样式复用现有 popup。
|
||||
- 3D 支持与 2D 一致的锚点点击行为,点击后打开同一套详情弹框逻辑。
|
||||
- 菜单切换、图层树勾选、图例勾选后,3D 锚点与 2D 一样联动变化。
|
||||
- 3D 必须复用 `eng_point` 的层级显示规则,中型水电站仅在 `ENG_POINT_MEDIUM_VISIBLE_ZOOM = 7.5` 以上显示。
|
||||
|
||||
## 2. 2D 现状梳理
|
||||
|
||||
当前 `2D` 的能力并不是散落在页面里,而是已经形成了比较清晰的分层:
|
||||
|
||||
### 2.1 页面入口
|
||||
|
||||
- `src/components/gis/GisView.vue`
|
||||
- 负责挂载地图容器、popup 容器、地图控制器、图例、图层树。
|
||||
- 页面只调用 `mapOrchestrator.mountView()` 和 `handlePageChange()`,不直接拼地图业务。
|
||||
|
||||
### 2.2 地图编排层
|
||||
|
||||
- `src/modules/map/application/map-orchestrator.ts`
|
||||
- 负责页面初始化、菜单切换、图层配置加载、图例配置加载、基地切换、缩放联动。
|
||||
- 2D/3D 都应尽量复用这一层,避免在 Cesium 侧另起一套业务流程。
|
||||
|
||||
### 2.3 地图统一门面
|
||||
|
||||
- `src/components/gis/map.class.ts`
|
||||
- 对外暴露统一接口,如:
|
||||
- `addBaseDataLayer`
|
||||
- `addInitDataLayer`
|
||||
- `mdLayerTreeShowOrHidden`
|
||||
- `setLegendPointVisible`
|
||||
- `controlBaseLayerTreeShowAndHidden`
|
||||
- `initPopupOverlay`
|
||||
- `flyTopanto`
|
||||
- 业务层只认这套接口,不应感知底层是 `OpenLayers` 还是 `Cesium`。
|
||||
|
||||
### 2.4 2D 地图能力落点
|
||||
|
||||
- `src/components/gis/map.ol.ts`
|
||||
- 已实现的关键能力:
|
||||
- 默认中国视角初始化
|
||||
- 基础底图加载与切换
|
||||
- 点位图层注册和显隐
|
||||
- 图例控制单类锚点显隐
|
||||
- 鼠标 hover popup
|
||||
- click 打开详情弹窗
|
||||
- 基地裁切与底图遮罩
|
||||
- 缩放/移动后的批量 popup 和标签刷新
|
||||
|
||||
### 2.5 2D 锚点与 popup 支撑
|
||||
|
||||
- `src/components/gis/ol/point-layer-manager.ts`
|
||||
- 负责将点位数据转成地图要素、分层、索引、图例显隐。
|
||||
- `src/components/gis/ol/popup-manager.ts`
|
||||
- 负责 hover 命中、popup DOM 内容复用、批量 popup。
|
||||
|
||||
### 2.6 图层树和图例交互
|
||||
|
||||
- `src/components/mapController/LayerController.vue`
|
||||
- 图层树勾选后走 `mapOrchestrator.applyLayerSelection()`
|
||||
- `src/components/mapLegend/index.vue`
|
||||
- 图例点击后走 `mapOrchestrator.toggleLegend()` / `toggleLegendBatch()`
|
||||
- `src/store/modules/map.ts`
|
||||
- 真正把缓存数据、图层状态、图例状态应用到地图实例
|
||||
- 也就是说,`3D` 只要把统一接口补齐,就能直接接住现有业务流
|
||||
|
||||
### 2.7 2D 已有特殊业务规则
|
||||
|
||||
- 锚点点击逻辑已在 `src/components/gis/map.ol.ts` 实现:
|
||||
- 命中锚点后,`ylfb` 走 `ylfbModalVisible`
|
||||
- 其他锚点走 `modalVisible`
|
||||
- 标题和参数都直接取当前锚点数据
|
||||
- `eng_point` 的中型水电站显示阈值已在现有链路中实现:
|
||||
- 阈值常量位于 `src/modules/map/application/map-orchestrator.ts`
|
||||
- 过滤逻辑位于 `src/store/modules/map.ts` 的 `filterPointLayerDataForDisplay()`
|
||||
- `3D` 不应重新发明一套规则,而应复用这套现有过滤结果
|
||||
- 部分点位会随着缩放级别提升显示得更多,不是简单的“图层开/关”:
|
||||
- `eng_point` 的中型电站要到 `ENG_POINT_MEDIUM_VISIBLE_ZOOM = 7.5` 以上才显示
|
||||
- 水电开发页在缩放跨过 `12` 级时会自动补开一批动态图层
|
||||
- `2D` 内部还存在点位密度阈值、近邻点展开、批量 popup 阈值等缩放联动规则
|
||||
- `2D` 对锚点存在碰撞检测与密度控制,不是所有点始终全量显示:
|
||||
- 图标和标签会分别经过碰撞计算
|
||||
- 低缩放下会因为密度、碰撞、区域裁切、图例状态而隐藏部分点
|
||||
- 高缩放下会逐步放开限制,显示更多锚点和标签
|
||||
|
||||
## 3. 3D 当前现状与缺口
|
||||
|
||||
### 3.1 已有内容
|
||||
|
||||
- `src/components/gis/map.cesium.ts`
|
||||
- 当前只完成了最小化 `Cesium.Viewer` 初始化。
|
||||
- 已有基础缩放、截图、`flyTopanto()` 雏形。
|
||||
|
||||
### 3.2 当前主要缺口
|
||||
|
||||
- `init()` 里虽然定义了 `flyToChina()`,但没有真正执行,也没有 `resolve(viewer)`,初始化流程不完整。
|
||||
- 默认底图仍是 ArcGIS 全球影像,因此启动时容易落到美国默认视角。
|
||||
- `addBaseDataLayer()` 为空,无法接住当前 `GISMap/customBaseLayer` 逻辑。
|
||||
- `addInitDataLayer()` 为空,无法展示锚点。
|
||||
- `mdLayerTreeShowOrHidden()` 为空,菜单切换时 3D 锚点不会同步显隐。
|
||||
- `setLegendPointVisible()` 为空,图例勾选不会影响 3D 锚点。
|
||||
- `initPopupOverlay()` 为空,无法复用 2D popup 容器。
|
||||
- 缺少点击命中与详情弹框联动,3D 当前无法做到“点击锚点与 2D 同行为”。
|
||||
- `controlBaseLayerTreeShowAndHidden()` 为空,3D 基础底图和叠加层无法受现有图层树控制。
|
||||
- 尚未验证 `eng_point` 的缩放阈值规则在 3D 下是否能完全复用,存在实现时遗漏中型站点显隐的风险。
|
||||
- 目前没有承接 `2D` 中“放大到具体层级显示更多锚点”的缩放联动显示机制。
|
||||
- 目前没有承接 `2D` 中图标/标签的碰撞检测逻辑,后续若直接全量渲染,视觉效果会与 `2D` 明显不一致。
|
||||
- 当前没有建立 `Cesium entity / datasource / imageryLayer` 的注册表,后续联动无从下手。
|
||||
|
||||
## 4. 实施原则
|
||||
|
||||
- 不重做业务编排,优先复用 `map-orchestrator.ts` 和 `src/store/modules/map.ts`。
|
||||
- 不额外引入一套 3D 专用图例和图层状态,仍以现有 store 为唯一运行态来源。
|
||||
- 不单独复制 `eng_point` 的中型站显示规则,优先复用现有 `mapStore` 过滤结果。
|
||||
- 不单独新建一套点击弹框协议,优先保持与 `map.ol.ts` 相同的命中后行为。
|
||||
- 对“缩放越大显示越多锚点”这类规则,优先复用现有缩放阈值与显示门闩,不做拍脑袋的新规则。
|
||||
- 对碰撞检测,优先与 `2D` 保持同方向行为:低缩放控量,高缩放放开,而不是 3D 全量堆点。
|
||||
- 先做最小闭环,再逐步补能力:
|
||||
- 第一步保证 3D 能正确初始化并定位中国。
|
||||
- 第二步保证基础底图能显示。
|
||||
- 第三步保证锚点能显示。
|
||||
- 第四步保证 popup、图层树、图例联动打通。
|
||||
- 3D 不做“基础地图切换 UI”,但底层仍要支持 `customBaseLayer + addBaseDataLayer(..., true)` 这一逻辑。
|
||||
|
||||
## 5. 分步骤实施计划
|
||||
|
||||
### Step 1:修正 3D 初始化并默认定位中国 ✅️
|
||||
|
||||
目标:
|
||||
|
||||
- 切到 3D 后稳定初始化 viewer。
|
||||
- 首屏出现一个轻量加载动画。
|
||||
- 初始化完成后飞到中国默认视角。
|
||||
|
||||
计划:
|
||||
|
||||
- 修复 `map.cesium.ts` 的 `init()`:
|
||||
- 保证初始化后一定 `resolve(this.viewer)`。
|
||||
- 执行 `flyToChina()`。
|
||||
- 补一个可控的启动过渡动画。
|
||||
- 统一中国默认参数:
|
||||
- 中心经纬度建议复用 `104.5, 36.5`
|
||||
- 相机高度先按全国视角收口,后续再微调
|
||||
- 如果切回 2D 再切到 3D,仍然要能正确重建 viewer。
|
||||
|
||||
验收:
|
||||
|
||||
- 点击 `3D` 按钮后,不再出现美国默认视角。
|
||||
- 首屏有加载过渡。
|
||||
- 进入后稳定落在中国。
|
||||
|
||||
### Step 2:展示 3D 基础底图 ✅️
|
||||
|
||||
目标:
|
||||
|
||||
- 3D 不显示空球。
|
||||
- 保留“基础底图 + 3D 专用底图地址”能力。
|
||||
- 不提供底图切换面板,但底层能吃现有配置。
|
||||
|
||||
计划:
|
||||
|
||||
- 在 `MapCesium` 内建立基础图层注册表。
|
||||
- 实现 `addBaseDataLayer(layer, isShow)`:
|
||||
- 对 `customBaseLayer` 使用 `url_3d`
|
||||
- 对 `BASEMAP-img`、`BASEMAP-white` 预留兼容能力
|
||||
- **必须处理 `wmts` 类型图层**:2D 通过 `WMTS` source 加载,3D 使用 `Cesium.WebMapTileServiceImageryProvider`,从 URL 参数中提取 LAYER/TILEMATRIXSET
|
||||
- **必须提供 `tileMatrixLabels`**:Cesium 默认用纯数字作为 tileMatrix 参数值,但本系统 WMTS 服务器要求 `TileMatrixSet:zoom` 格式(如 `EPSG:3857_hbb_zrbhq_l13:4`)。需构建 `["TileMatrixSet:0", "TileMatrixSet:1", ...]` 传入 `tileMatrixLabels`。
|
||||
- 其他类型:`raster-dem`→XYZ、MapServer→ArcGIS、其余 →WMS
|
||||
- **注意**:还存在一个 `key = "powerBaseStation"` 的基地底图图层,该图层**初始化时不加载**(已在 `IGNORED_BASE_LAYER_KEYS` 中忽略),但后续可通过图层树手动勾选显示。
|
||||
- 实现 `controlBaseLayerTreeShowAndHidden()`:
|
||||
- 让图层树勾选能控制 3D 底图显隐
|
||||
- 根据你的要求,UI 层先不开放 `BaseLayerSwitcher` 的 3D 切换行为,只保留默认基础底图加载。
|
||||
|
||||
验收:
|
||||
|
||||
- 切到 3D 后可稳定看到基础底图。
|
||||
- 图层初始化时 `addBaseDataLayer(this.baseLayerConfig, checked, true)` 的思路在 3D 可落地。
|
||||
|
||||
### Step 3:打通 3D 锚点展示 ✅️
|
||||
|
||||
目标:
|
||||
|
||||
- 3D 能展示和 2D 同源的锚点数据。
|
||||
- 菜单切换后,3D 能跟随页面数据切换。
|
||||
|
||||
计划:
|
||||
|
||||
- 在 `MapCesium` 内建立点位图层注册结构,按 `layerKey -> entity[]` 管理。
|
||||
- 实现 `addInitDataLayer(pointData, layerType)`:
|
||||
- 复用当前点位数据结构
|
||||
- 解析 `lgtd/lttd/iconCode/titleName/stnm/anchoPointState/popupHtml`
|
||||
- 复用现有图标资源路径
|
||||
- Entity ID 使用 `${layerKey}:${item._id || `${iconType || 'point'}_${stcd}`}`,与 2D 对齐,确保同 stcd 不同 sttpMap 的点不被覆盖
|
||||
- 确保 `eng_point` 仍按现有 `mapStore` 过滤后的数据展示,中型站点只在 `7.5` 以上层级出现
|
||||
- 为后续缩放驱动的增量显示预留运行态字段(`_legendVisible`、`_regionVisible`、`_densityVisible`),不把所有点简单一次性硬渲染
|
||||
- 实现 `mdLayerTreeShowOrHidden(layerType, checked)`:
|
||||
- 图层树控制整个点图层显隐
|
||||
- 实现 `removePointLayer()` / `hasLayer()`
|
||||
- 便于后续页面切换和重载
|
||||
|
||||
验收:
|
||||
|
||||
- 切到 3D 后当前页默认勾选图层的锚点能显示。
|
||||
- 切换菜单后,3D 锚点跟随变化。
|
||||
- 取消勾选图层后,对应锚点消失。
|
||||
- `eng_point` 在低于 `7.5` 时不显示中型水电站,高于 `7.5` 时正常显示。
|
||||
|
||||
### Step 4:打通 3D 基地裁切(jdPanelControlShowAndHidden) ✅️
|
||||
|
||||
目标:
|
||||
|
||||
- 3D 点击基地面板后,与 2D 行为一致。
|
||||
- 加载基地边界 GeoJSON,只显示区域内锚点,隐藏区域外锚点。
|
||||
- 取消基地时恢复显示所有锚点。
|
||||
|
||||
计划:
|
||||
|
||||
- 在 `MapCesium` 中捕获 `hydropBase` 配置,与 2D 一样在 `addBaseDataLayer` 中记录。
|
||||
- 实现 `jdPanelControlShowAndHidden(baseid, isAll)`:
|
||||
- `isAll=false`:清除 3D 球面遮罩实体、恢复所有锚点区域可见性、清除裁切状态。
|
||||
- `isAll=true`:先隐藏所有锚点,异步加载基地边界 GeoJSON,执行点在面判断后仅显示区域内锚点,同时在球面绘制裁切边界多边形(`applyRegionMask`),最后飞行到区域视野。
|
||||
- 在 `createEntityPropertiesBag` 中新增 `_regionVisible` 属性,初始为 `true`。
|
||||
- 在 `applyPointVisibilityRefresh` 中跳过 `_regionVisible !== false` 的实体,确保裁切后碰撞检测不会把区域外锚点重新显示出来。
|
||||
- 复用 `extractPolygonCoords` / `isPointInRing` 射线法判断逻辑(与 `region-mask-manager.ts` 一致)。
|
||||
- 支持 `AbortController` 取消前一次未完成的请求,避免响应顺序错乱。
|
||||
- `applyRegionMask` 将 GeoJSON 多边形转换为 Cesium `PolygonHierarchy`,在球面绘制半透明填充 + 可见边界的区域多边形,模拟 2D 底图 Canvas 裁切遮罩的视觉效果。
|
||||
|
||||
验收:
|
||||
|
||||
- 点击基地后,3D 只显示该基地区域内的锚点,区域外锚点隐藏。
|
||||
- 取消基地后,所有锚点恢复正常显示。
|
||||
- 快速切换基地不会出现旧数据覆盖新数据的问题。
|
||||
- 多次切换 2D/3D 后基地裁切行为正常。
|
||||
|
||||
### Step 5:打通 3D popup 与 hover ✅️
|
||||
|
||||
目标:
|
||||
|
||||
- 3D 鼠标悬停时显示与 2D 一样的 popup。
|
||||
- popup 样式复用现有 DOM 和样式,不再单独做一版。
|
||||
|
||||
计划:
|
||||
|
||||
- 实现 `initPopupOverlay(popupContainer)`
|
||||
- 继续复用 `GisView.vue` 中现有 popup 容器
|
||||
- 在 Cesium 中增加鼠标移动命中:
|
||||
- 基于 `ScreenSpaceEventHandler`
|
||||
- hover 到锚点时读取 entity 附带属性
|
||||
- popup 内容生成逻辑复用 2D 现有字段:
|
||||
- 优先使用 `popupHtml`
|
||||
- 否则走通用字段渲染
|
||||
- 处理离开锚点时隐藏 popup。
|
||||
|
||||
验收:
|
||||
|
||||
- 鼠标移入锚点出现 popup。
|
||||
- 样式和 2D 保持一致。
|
||||
- 移出后 popup 正常消失。
|
||||
|
||||
### Step 6:补齐缩放驱动显示与碰撞检测
|
||||
|
||||
目标:
|
||||
|
||||
- 3D 在低缩放下控制锚点数量,避免全量堆叠。
|
||||
- 3D 在放大到具体层级后,逐步显示更多锚点。
|
||||
- 3D 的图标/标签显示效果尽量接近 2D,不出现严重遮挡。
|
||||
|
||||
计划:
|
||||
|
||||
- 先承接现有明确可复用的缩放规则:
|
||||
- `eng_point` 的 `7.5` 阈值
|
||||
- 水电开发页的 `12` 级动态图层联动
|
||||
- 再补 3D 侧的显示门闩:
|
||||
- 低缩放下根据缩放级别、图层状态、图例状态控制 entity 显隐
|
||||
- 高缩放下逐步放开限制,显示更多锚点
|
||||
- 为 3D 补一版轻量碰撞控制:
|
||||
- 至少先控制标签碰撞,避免名称完全叠在一起
|
||||
- 如有必要,再补图标级碰撞或屏幕网格抽稀
|
||||
- 明确与 2D 对齐的目标不是“算法完全一样”,而是“视觉行为一致”:
|
||||
- 低缩放控量
|
||||
- 高缩放增量显示
|
||||
- 关键锚点不被完全淹没
|
||||
|
||||
验收:
|
||||
|
||||
- 3D 在全国视角下不会一次性挤满所有锚点。
|
||||
- 放大到具体层级后会看到更多锚点逐步出现。
|
||||
- 标签和锚点不会大面积重叠到不可读。
|
||||
|
||||
### Step 7:打通 3D 锚点点击详情 ✅️
|
||||
|
||||
目标:
|
||||
|
||||
- 3D 点击锚点后,行为与 2D 一致。
|
||||
- 继续复用现有详情弹框状态和参数结构。
|
||||
|
||||
计划:
|
||||
|
||||
- 在 Cesium 中增加点击命中:
|
||||
- 基于 `ScreenSpaceEventHandler`
|
||||
- 命中锚点后读取 entity 绑定的原始业务数据
|
||||
- 复用 `2D` 当前点击行为:
|
||||
- `sttpMap === 'ylfb'` 时打开 `ylfbModalVisible`
|
||||
- 其他锚点打开 `modalVisible`
|
||||
- `params`、`title` 赋值逻辑与 `map.ol.ts` 保持一致
|
||||
- 避免 hover popup 与 click 弹框互相干扰。
|
||||
|
||||
验收:
|
||||
|
||||
- 点击 3D 锚点后可打开与 2D 一致的详情弹框。
|
||||
- `ylfb` 和普通锚点分支行为一致。
|
||||
- 点击空白区域不会误触发弹框。
|
||||
|
||||
### Step 8:打通图例联动 ✅️
|
||||
|
||||
目标:
|
||||
|
||||
- 图例勾选后,3D 只显示对应状态的锚点。
|
||||
|
||||
计划:
|
||||
|
||||
- 实现 `setLegendPointVisible(layerKey, anchoPointState, checked)`:
|
||||
- 复用 `anchoPointState` 作为图例匹配字段
|
||||
- entity 级别维护显示状态
|
||||
- 如果后续需要,也可补一个 3D 版本的图例索引表,避免每次全量遍历。
|
||||
|
||||
验收:
|
||||
|
||||
- 图例单项勾选/取消时,3D 对应类别锚点同步显隐。
|
||||
- 图例分组勾选/取消时,3D 行为与 2D 保持一致。
|
||||
|
||||
### Step 9:补足收口与稳定性 ✅️
|
||||
|
||||
目标:
|
||||
|
||||
- 让 3D 能稳定参与现有地图生命周期。
|
||||
|
||||
计划:
|
||||
|
||||
- 清理 Cesium 事件监听、viewer、entity、datasource,避免重复切换内存泄漏。
|
||||
- 检查 `switchView('2D' | '3D')` 前后 popup、底图、图层注册是否被正确重置。
|
||||
- 检查 hover、click、图例、图层树、缩放阈值这几条联动链路在 3D 是否完全闭环。
|
||||
- 视情况补最小诊断日志,确认菜单切换与图层联动没有漏项。
|
||||
|
||||
验收:
|
||||
|
||||
- 2D/3D 多次来回切换不报错。
|
||||
- 菜单切换、图层切换、图例切换行为稳定。
|
||||
|
||||
## 6. 推荐落地顺序
|
||||
|
||||
按你的要求,建议严格按下面顺序推进:
|
||||
|
||||
1. 默认定位到中国 + 启动动画
|
||||
2. 展示基础底图
|
||||
3. 展示锚点 3.5. 补基地裁切(jdPanelControlShowAndHidden)
|
||||
4. 补 hover popup
|
||||
5. 补缩放驱动显示与碰撞检测
|
||||
6. 补锚点点击详情
|
||||
7. 补图层树联动
|
||||
8. 补图例联动
|
||||
9. 做切换稳定性收口
|
||||
|
||||
## 7. 预计修改文件
|
||||
|
||||
- `src/components/gis/map.cesium.ts`
|
||||
- 3D 地图主体实现,主改动文件
|
||||
- `src/components/gis/map.class.ts`
|
||||
- 视情况补齐 2D/3D 切换后 popup 初始化和服务切换细节
|
||||
- `src/components/gis/GisView.vue`
|
||||
- 视情况控制 3D 下的底图切换器显示策略、加载态挂载位置
|
||||
- `src/components/mapController/index.vue`
|
||||
- 若需要补 3D 初始化后的交互控制
|
||||
|
||||
## 8. 当前建议
|
||||
|
||||
建议先只做 `Step 1`,也就是:
|
||||
|
||||
- 修正 Cesium 初始化完成逻辑
|
||||
- 增加 3D 启动加载动画
|
||||
- 默认飞到中国
|
||||
|
||||
这一步最小、最容易验证,也能先把“打开 3D 看起来不对”的核心问题解决掉。
|
||||
|
||||
## 9. 必须补齐的隐藏逻辑清单
|
||||
|
||||
下面这些逻辑不是表面接口能直接看出来的,但如果 `3D` 不补,最终效果就会和 `2D` 明显不一致。
|
||||
|
||||
### 9.1 图层与菜单切换 ✅️
|
||||
|
||||
- ✅ 菜单切换时,只隐藏旧页点图层,不隐藏底图。(编排器 `handlePageChange` 控制,Cesium 被动接收数据)
|
||||
- ✅ 图层树勾选前要先经过互斥规则归一化:(store 层 `updateLayerData` 处理,Cesium 不感知)
|
||||
- `rare_fish_point` 与 `fish_along_point` 互斥
|
||||
- `stinfo/stinfo_video_point` 与 `stinfo_ai_video_point` 互斥
|
||||
- `facilities` 与 `facilities_built` 两个分支互斥
|
||||
- ✅ 点图层取消勾选时只隐藏,不删除缓存;重新勾选时优先从缓存恢复。`mdLayerTreeShowOrHidden` 设置 `_layerVisible` 标志,不删除 `pointLayerRegistry` 条目。
|
||||
- ✅ **图层树勾选时按 `type` 字段走不同分支**(见 `updateLayerData`,store 层处理):
|
||||
- `type === 'pointMap'` → 走 `handlePointMapLayer` → 调用 `mdLayerTreeShowOrHidden`(已实现,L1624)
|
||||
- `type === 'GISMap'` → 走 `controlBaseLayerTreeShowAndHidden`(已实现,L1345)
|
||||
- 3D Cesium 已同时实现这两个方法。
|
||||
|
||||
### 9.2 图例与点内显隐 ✅️
|
||||
|
||||
- ✅ 图例控制的是图层内部锚点是否可见,不是图层本身是否可见。`setLegendPointVisible` 使用 `_legendVisible` 标志,与 `_layerVisible` 独立。
|
||||
- ✅ 图层恢复显示时,图例要先整层全关,再按当前 checked 状态逐项恢复。支持 `anchoPointState=''` 全关 → 逐项 `(state, true)` 恢复两步模式(L1764-1787)。
|
||||
- ✅ 环保设施图例组当前是只展示不交互。(编排器层面控制,Cesium 不感知)
|
||||
|
||||
### 9.3 缩放驱动显示 ✅️
|
||||
|
||||
- ✅ `eng_point` 的中型水电站只在 `ENG_POINT_MEDIUM_VISIBLE_ZOOM = 7.5` 以上显示。(store `filterPointLayerDataForDisplay` 在数据进入 Cesium 前过滤)
|
||||
- ✅ 水电开发页缩放跨过 `12` 级时,会自动补开一批动态图层;缩回去时再自动收口。(编排器层面处理)
|
||||
- ✅ `2D` 存在"缩放越大显示越多"的行为。碰撞检测中密度门控逐级放开。
|
||||
- ✅ `2D` 还存在 hover、批量 popup、密度控制等缩放阈值:
|
||||
- hover 低于 ~zoom 4.5 不触发(`HOVER_POPUP_MAX_HEIGHT = 9_000_000`)
|
||||
- 高缩放进入批量 popup 模式(`BATCH_POPUP_MODE_ZOOM = 14.9`)
|
||||
- 点位随着缩放提升逐步放开密度限制(密度门控 + `DENSITY_ISOLATION_THRESHOLD`)
|
||||
- ✅ **图标动态缩放**:`CallbackProperty` 实现 `billboard.scale`,公式 `clamp(0.7 + (zoom - 4.5) * 0.035, 0.4, 1.2)`(L1522)。
|
||||
- ✅ **字体动态大小**:`CallbackProperty` 实现 `label.font`,钳位 `[10, 20]`(L1535)。
|
||||
- ✅ **文字在图标上方**:`CallbackProperty` 实现 `label.pixelOffset`,负 Y 偏移(L1549)。
|
||||
- ✅ **Cesium 中必须使用 `CallbackProperty` 实现动态缩放**:已使用 3 个 `CallbackProperty`(scale/font/offset),`isConstant=false` 每帧重算。
|
||||
|
||||
### 9.4 锚点碰撞与控量 ✅️
|
||||
|
||||
- ✅ `2D` 中锚点是否可见,不只受图层开关控制,还受以下门闩共同影响:
|
||||
- 图例可见性 `_legendVisible`
|
||||
- 区域裁切可见性 `_regionVisible`
|
||||
- 密度阈值(碰撞循环中 inline 计算,逐级放开)
|
||||
- 图标碰撞结果 `_iconCollisionVisible`
|
||||
- 标签碰撞结果 `_labelCollisionVisible`
|
||||
- ✅ 低缩放下,为避免堆叠,部分锚点或标签会被主动隐藏。(`refreshPointLabelVisibility` 碰撞检测,L2117-2455)
|
||||
- ✅ 高缩放下,会逐步放开图标/标签限制,显示更多内容。(密度门控 + 碰撞容差随 zoom 调整)
|
||||
- ✅ 因此 `3D` 不能简单把所有 entity 永久全开。所有 entity 初始 `_iconCollisionVisible = _labelCollisionVisible = true`,碰撞检测运行后动态调整。
|
||||
|
||||
### 9.5 Popup 与点击 ✅️
|
||||
|
||||
- ✅ hover popup 不是全时开启的,有缩放门槛。相机高度 > `HOVER_POPUP_MAX_HEIGHT` 时不触发 hover。
|
||||
- ✅ 点击和 hover 的命中对象是图标本体,不是任意文字区域。`ScreenSpaceEventHandler` 基于 `scene.pick` 命中 entity。
|
||||
- ✅ `ylfb` 与普通锚点的点击详情弹框走不同业务分支。`sttpMap === 'ylfb'` 打开 `ylfbModalVisible`,其他走 `modalVisible`(L366-375)。
|
||||
|
||||
### 9.6 基地与区域裁切 ✅️
|
||||
|
||||
- ✅ 基地切换不仅影响搜索候选,还会影响地图上的点位可见范围。`jdPanelControlShowAndHidden` 实现(L1684-1748)。
|
||||
- ✅ 区域裁切会直接把区域外点位隐藏,不是只改底图遮罩。`filterPointsByRegion` 设置 `_regionVisible = false`(L1824-1848),遮罩多边形 + 裁剪双重处理。
|
||||
|
||||
### 9.7 筛选器特殊逻辑 ✅️
|
||||
|
||||
- ✅ 装机容量筛选本质是批量切 `eng_point` 图例状态,不是简单切图层。(store 层处理,Cesium 通过 `setLegendPointVisible` 响应)
|
||||
- ✅ 鱼类分布模式会接管 `ylfb_point` 的数据、缓存、图例与显隐。(store 层处理)
|
||||
- ✅ 时间筛选当前只重载指定时间相关图层,不是全量重载。(store 层处理)
|
||||
|
||||
### 9.8 数据进入 addInitDataLayer 前的预处理 ✅️
|
||||
|
||||
- ✅ 所有点位数据在进入 `addInitDataLayer` 前会经过 `normalizePointLayerItems()` 过滤:(store 层 `map.ts` 执行,Cesium 接收时已过滤)
|
||||
- 没有 `iconCode` 且 `code !== 'colorLayer'` 的项会被抛弃
|
||||
- `baseId == 'all'` 且 `anchoPointState` 结尾为 `_nbuilt` 的项会被抛弃
|
||||
- ✅ `_id` 默认值生成规则:store 层生成 `${sttpMap || iconType || 'point'}_${stcd}`。
|
||||
- ✅ **stcd+经纬度重复锚点处理**:Cesium entity ID 使用 `${layerKey}:${item._id}`,与 2D 对齐,同 stcd 不同 sttpMap 的点不会互相覆盖。
|
||||
|
||||
### 9.9 图标渐进加载机制
|
||||
|
||||
- ❌ 2D 中图标不是一次性全加载完。有 `loading → loaded → error` 三种状态跟踪。
|
||||
- ❌ 只有 `loaded` 状态的图标才参与样式渲染,loader 失败的不渲染。
|
||||
- ❌ 如果在图标加载过程中就触发了样式刷新,需要通过 `requestAnimationFrame` 回刷。
|
||||
- ❌ 3D Cesium 中当前所有 entity 同步创建,billboard `image` URL 直接赋值,无渐进加载。Cesium 内部纹理加载无显式状态跟踪。
|
||||
|
||||
### 9.10 密度分档与近邻点元数据 ✅️
|
||||
|
||||
- ✅ 每个锚点的 `distance` 字段表示密度分档值(不是物理距离),值越大表示越稀疏。(已使用 `getEntityDensityValue` 从 `_rawData.distance` 读取,L2460)
|
||||
- ✅ 不同 density 值对应不同的 `minZoom` 显示门槛。`getEntityDensityMinZoom` 映射 `nearby-point-rules.ts` 的 `densityDisplayRules`(L2491)。
|
||||
- ✅ 全量数据加载后,store 会调用 `attachNearbyPointRuntimeMeta()` 给所有点打上 `_nearbyRule`、`_nearbyGroupId`、`_nearbyPriority` 等元数据。(store 层处理,Cesium 碰撞检测中读取)
|
||||
- ✅ **孤立点例外规则**:如果一个点在当前视口内 ~56px 范围内没有同 layerKey 的其他可见点,它可以绕过密度门槛直接显示。`DENSITY_ISOLATION_THRESHOLD = 56` + `shouldBypassDensityGateForIsolatedEntity`(L2506-2556)。
|
||||
343
frontend-sjgl/docs/地图模块-OpenLayers抽吸与碰撞分析.md
Normal file
@ -0,0 +1,343 @@
|
||||
# 地图模块-OpenLayers抽吸与碰撞分析
|
||||
|
||||
## 1. 背景
|
||||
|
||||
当前地图 2D 主引擎已经切换为 OpenLayers,项目依赖版本为 `ol@^10.8.0`。
|
||||
本次关注的问题有两个:
|
||||
|
||||
- 点位“抽吸”逻辑不符合业务预期;
|
||||
- 文字碰撞时把整个点位一起隐藏,而不是仅隐藏文字。
|
||||
|
||||
典型场景是两个相邻电站,例如“积石峡”和“公伯峡”:
|
||||
|
||||
- 可用代号 `1`、`2` 表示两个相邻点;
|
||||
- 默认缩放下只展示 `1`;
|
||||
- 放大到某个层级后,`1` 隐藏,`2` 展示;
|
||||
- 再继续放大后,`1` 和 `2` 都展示,但 `2` 需要“抽吸/拉开”显示,避免与 `1` 重叠;
|
||||
- 如果只是文字发生碰撞,希望点图标保留,仅文字隐藏或延后显示。
|
||||
|
||||
本文件先整理当前代码现状和问题成因,不直接修改实现。
|
||||
如果需要查看**当前已经落地的抽吸规则、默认参数和调参入口**,请同时参考:
|
||||
|
||||
- `docs/地图模块-抽吸规则与参数说明.md`
|
||||
|
||||
## 2. 当前代码结构
|
||||
|
||||
当前前端 GIS 运行链路如下:
|
||||
|
||||
1. `src/components/gis/GisView.vue`
|
||||
2. `src/modules/map/application/map-orchestrator.ts`
|
||||
3. `src/components/gis/map.class.ts`
|
||||
4. `src/components/gis/map.ol.ts`
|
||||
5. `src/components/gis/ol/point-layer-manager.ts`
|
||||
6. `src/components/gis/ol/popup-manager.ts`
|
||||
|
||||
各层职责简述:
|
||||
|
||||
- `GisView.vue`
|
||||
- 地图入口组件;
|
||||
- 挂载地图容器、图例、筛选器、控制器;
|
||||
- 通过 `mapOrchestrator.mountView()` 初始化地图;
|
||||
- 菜单切换时通过 `handlePageChange()` 触发页面地图重载。
|
||||
|
||||
- `map.class.ts`
|
||||
- 地图门面类;
|
||||
- 当前 2D 实现实际绑定的是 `MapOl`;
|
||||
- 3D 实现才会切到 `MapCesium`。
|
||||
|
||||
- `map.ol.ts`
|
||||
- OpenLayers 主实现;
|
||||
- 负责地图初始化、底图加载、点位样式、Popup、区域裁切、量算等;
|
||||
- 当前“点位渲染规则”和“碰撞相关逻辑”主要集中在这个文件。
|
||||
|
||||
- `point-layer-manager.ts`
|
||||
- 负责点图层创建、Feature 灌入、按图层控制显隐;
|
||||
- 点位图层统一使用 `VectorLayer + VectorSource`。
|
||||
|
||||
- `popup-manager.ts`
|
||||
- 管理 hover popup 和高缩放下的批量 popup;
|
||||
- 内部额外做了一套基于边界框的碰撞判断。
|
||||
|
||||
## 3. 当前点位渲染链路
|
||||
|
||||
### 3.1 点图层创建
|
||||
|
||||
`point-layer-manager.ts` 中的 `ensureLayer()` 会统一创建点图层:
|
||||
|
||||
- 图层类型为 `VectorLayer<VectorSource>`;
|
||||
- 图层上开启了 `declutter: true`;
|
||||
- 样式函数统一走 `map.ol.ts` 中的 `createPointStyle()`。
|
||||
|
||||
也就是说,当前所有点位的“是否显示”和“图标/文字如何避让”,都收敛到 OpenLayers 的 declutter 机制和样式函数里。
|
||||
|
||||
### 3.2 点样式生成
|
||||
|
||||
`map.ol.ts` 的 `createPointStyle()` 当前做了这些事:
|
||||
|
||||
- 读取 `_iconUrl` 和 `_labelText`;
|
||||
- 如果图例不可见、区域不可见,则直接返回 `null`;
|
||||
- 如果 `distance` 不满足当前缩放级别要求,也直接返回 `null`;
|
||||
- 图标使用 `Icon`;
|
||||
- 文字使用 `Text`;
|
||||
- 图标和文字都设置了 `declutterMode: 'declutter'`;
|
||||
- 最终把图标和文字一起放进同一个 `Style` 返回。
|
||||
|
||||
这意味着:
|
||||
|
||||
- 点图标和文字不是两个独立的渲染对象;
|
||||
- 它们在当前实现中属于同一个样式结果;
|
||||
- 只要这组样式参与碰撞判定,图标和文字的命运就是绑定的。
|
||||
|
||||
### 3.3 当前已有的“抽稀”逻辑
|
||||
|
||||
当前项目中确实有一层“缩放越小,显示越少”的处理,但它不是精细的“抽吸”。
|
||||
|
||||
`map.ol.ts` 的 `shouldRenderFeatureByDistance()` 逻辑是:
|
||||
|
||||
- 小缩放下要求 `distance` 更大才允许显示;
|
||||
- 缩放越大,允许显示的点逐渐增多;
|
||||
- 本质上是基于后端数据字段 `distance` 做全局抽稀。
|
||||
|
||||
这个逻辑的特点是:
|
||||
|
||||
- 是全局阈值,不是成对点位或同组点位的专属规则;
|
||||
- 只能决定“这个点显示还是不显示”;
|
||||
- 不能表达“1 和 2 是近邻关系,并且在不同缩放阶段按业务优先级切换显示”。
|
||||
|
||||
### 3.4 当前批量 Popup 的碰撞检测
|
||||
|
||||
`popup-manager.ts` 在高缩放批量 popup 模式下,又额外做了一层碰撞判断:
|
||||
|
||||
- 先估算图标和文字合并后的锚点边界框;
|
||||
- 如果边界框碰撞,则当前要素直接不参与 popup 渲染;
|
||||
- 随后再判断 popup 矩形之间是否碰撞。
|
||||
|
||||
这说明当前“图标 + 文字”被视为一个整体,不仅体现在 OpenLayers 的 declutter 里,也体现在 popup 的辅助判断里。
|
||||
|
||||
## 4. 当前仓库里“抽吸”相关代码现状
|
||||
|
||||
仓库中确实存在历史上的“抽吸”实现,但不在当前 OpenLayers 主链路里。
|
||||
|
||||
相关文件:
|
||||
|
||||
- `src/utils/leaflet/leaflet.inflatable-markers-group.js`
|
||||
- `src/components/gis/map.leaflet.ts`
|
||||
|
||||
现状判断:
|
||||
|
||||
- `leaflet.inflatable-markers-group.js` 是旧 Leaflet 时代的抽吸插件;
|
||||
- 它内部有 `inflateAsManyAsPossible()`、`_zoomend()` 等典型抽吸逻辑;
|
||||
- 但当前 `map.class.ts` 实际实例化的是 `new MapOl()`;
|
||||
- `map.leaflet.ts` 已经不在主运行路径上。
|
||||
|
||||
结论是:
|
||||
|
||||
- 当前页面上看到的点位行为,不是 Leaflet 抽吸插件在工作;
|
||||
- 现在的显示结果主要来自 OpenLayers 的 `declutter`、当前样式函数和 `distance` 抽稀逻辑;
|
||||
- 因此“已经有抽吸但是不太对”,更准确地说是“历史上有抽吸代码,但现在主链路没有真正使用那套机制”。
|
||||
|
||||
## 5. 问题分析
|
||||
|
||||
### 5.1 为什么当前实现做不到你要的分阶段抽吸
|
||||
|
||||
你描述的目标并不是简单“避让”,而是一个明确的分阶段显示策略:
|
||||
|
||||
1. 默认只显示 `1`;
|
||||
2. 缩放到阶段 A 时,隐藏 `1`,改为显示 `2`;
|
||||
3. 缩放到阶段 B 时,`1` 和 `2` 都显示;
|
||||
4. 阶段 B 下,`2` 还要相对 `1` 做抽吸/偏移,避免完全重叠。
|
||||
|
||||
而当前代码缺少以下能力:
|
||||
|
||||
- 没有“近邻点关系”配置
|
||||
- 代码里没有看到类似 `groupId`、`neighborIds`、`priority`、`displayLevel` 这样的结构;
|
||||
- 系统不知道“积石峡”和“公伯峡”是一组特殊近邻点。
|
||||
|
||||
- 没有“分阶段显示规则”配置
|
||||
- 当前只有全局的 `distance` 阈值判断;
|
||||
- 没有按缩放阶段表达“谁替代谁显示、谁先隐藏、谁后展示”。
|
||||
|
||||
- 没有“抽吸偏移”计算
|
||||
- 当前点要素坐标就是原始经纬度转换结果;
|
||||
- 没有根据缩放级别和邻近关系生成偏移坐标;
|
||||
- 也没有“展开后沿圆周/沿固定方向偏移”的逻辑。
|
||||
|
||||
- 当前 declutter 是被动避让,不是主动编排
|
||||
- declutter 只会尽量避免重叠;
|
||||
- 它不会理解业务上的“1 是主点、2 是附点”;
|
||||
- 也不会自动实现“先 1,后 2,再两个都展示且 2 偏移”的规则。
|
||||
|
||||
所以当前看到的结果不稳定,本质原因不是某一个参数不对,而是“现有机制和目标能力不是一类问题”。
|
||||
|
||||
### 5.2 为什么文字碰撞会把整个点隐藏
|
||||
|
||||
这是当前实现里最关键的原因:
|
||||
|
||||
- 点图标和文字是在同一个 `Style` 里返回的;
|
||||
- 图层开启了 `declutter: true`;
|
||||
- 图标和文字又都设置了 `declutterMode: 'declutter'`。
|
||||
|
||||
在这种组织方式下,当前要素的碰撞判定是按“一个整体渲染单元”处理的,而不是“图标一套规则,文字一套规则”。
|
||||
|
||||
因此会出现下面的现象:
|
||||
|
||||
- 图标本身其实不冲突;
|
||||
- 但文字边界框发生碰撞;
|
||||
- 最终被隐藏的是整条样式结果;
|
||||
- 用户视觉上就会觉得“明明只是字挤了,为什么点也没了”。
|
||||
|
||||
这和你现在观察到的问题是一致的。
|
||||
|
||||
### 5.3 为什么当前逻辑还会进一步放大这个问题
|
||||
|
||||
除了 OpenLayers 自身的 declutter 组织方式,代码里还有两层因素会继续放大问题:
|
||||
|
||||
- `shouldRenderFeatureByDistance()` 会先根据 `distance` 直接过滤点位;
|
||||
- `popup-manager.ts` 在批量 popup 模式下,也把“图标 + 文字”当作合并边界框做碰撞模拟。
|
||||
|
||||
也就是说,当前系统对近邻点位的处理是:
|
||||
|
||||
- 先用全局 `distance` 规则筛掉一部分;
|
||||
- 再用 OpenLayers declutter 继续过滤;
|
||||
- 高缩放时 popup 层再做一轮碰撞跳过。
|
||||
|
||||
这三层叠加后,显示行为更偏向“谁先撞谁消失”,而不是“按业务规则分阶段展开”。
|
||||
|
||||
## 6. 结合你的案例做具体映射
|
||||
|
||||
如果以近邻点 `1`、`2` 为例,当前代码里实际上缺的是下面这些业务语义:
|
||||
|
||||
- `1` 和 `2` 属于同一近邻组;
|
||||
- 组内有主次优先级;
|
||||
- 在不同 zoom 区间内有不同展示策略;
|
||||
- 在最大放大阶段需要给 `2` 一个偏移位;
|
||||
- 偏移后图标和文字还要分别控制碰撞策略。
|
||||
|
||||
当前实现只能表达:
|
||||
|
||||
- 某个点在当前 zoom 下是否允许渲染;
|
||||
- 某个点图例是否可见;
|
||||
- 某个点是否被区域裁切隐藏;
|
||||
- 某个点的图标和文字整体是否参与 declutter。
|
||||
|
||||
它并不能表达:
|
||||
|
||||
- “1 替代 2 展示”;
|
||||
- “2 替代 1 展示”;
|
||||
- “1 和 2 一起展示,但 2 抽吸展开”;
|
||||
- “只隐藏文字,不隐藏图标”。
|
||||
|
||||
所以你现在遇到的问题是结构性问题,不是简单调一个 `declutter` 参数就能彻底解决。
|
||||
|
||||
## 7. 后续修改时建议优先动的层
|
||||
|
||||
如果下一步要真正改这块,建议优先从下面几层入手:
|
||||
|
||||
### 7.1 先补“近邻点显示规则”
|
||||
|
||||
建议不要直接把业务规则写死在样式函数里,而是先增加一层近邻点编排规则,例如:
|
||||
|
||||
- `groupId`
|
||||
- `priority`
|
||||
- `showZoomMin`
|
||||
- `showZoomMax`
|
||||
- `replaceAtZoom`
|
||||
- `expandAtZoom`
|
||||
- `expandOffset`
|
||||
|
||||
这样才能表达:
|
||||
|
||||
- 默认只显示主点;
|
||||
- 中间层级切换成副点;
|
||||
- 更大层级两个都显示;
|
||||
- 副点在展示时做偏移。
|
||||
|
||||
### 7.2 抽吸不要依赖 declutter 自动完成
|
||||
|
||||
抽吸本质上是“主动布局”问题,不是“被动避让”问题。
|
||||
|
||||
建议后续把近邻点抽吸拆成单独逻辑:
|
||||
|
||||
- 先根据原始点数据识别近邻组;
|
||||
- 再根据当前 zoom 产出“本次真正参与渲染的点集合”;
|
||||
- 对需要展开的点,生成偏移后的渲染坐标;
|
||||
- 最后再交给图层渲染。
|
||||
|
||||
这样会比直接指望 OpenLayers 的 declutter 更可控。
|
||||
|
||||
### 7.3 图标层和文字层要分开控制
|
||||
|
||||
要实现“文字碰撞时只隐藏文字,不隐藏点图标”,后续最重要的一点是把图标和文字的渲染职责拆开。
|
||||
|
||||
至少要做到下面二选一:
|
||||
|
||||
- 图标层和文字层拆成两个独立图层;
|
||||
- 或者把图标与文字拆成可独立决策的渲染单元。
|
||||
|
||||
目标是:
|
||||
|
||||
- 图标优先保留;
|
||||
- 文字单独避让;
|
||||
- 文本碰撞时只压文字,不压图标。
|
||||
|
||||
如果仍然维持“同一个样式对象里同时放 image 和 text”的组织方式,这个问题大概率还会持续存在。
|
||||
|
||||
### 7.4 Popup 碰撞策略也要和新规则同步
|
||||
|
||||
后续如果点位抽吸和文字单独避让改了,`popup-manager.ts` 里的边界框逻辑也要一起调整。
|
||||
|
||||
否则会出现:
|
||||
|
||||
- 图标已经正常显示;
|
||||
- 文字也按新规则显示了;
|
||||
- 但 popup 层仍然沿用旧的合并边界框;
|
||||
- 最终又在 popup 阶段把结果打回去。
|
||||
|
||||
## 8. 建议的改造顺序
|
||||
|
||||
为了降低风险,建议后续改造按以下顺序推进:
|
||||
|
||||
1. 先梳理近邻点数据结构
|
||||
- 确定近邻点如何分组;
|
||||
- 确定主次优先级和缩放阈值从哪里来。
|
||||
|
||||
2. 再实现“显示决策层”
|
||||
- 在真正生成 Style 之前,先决定哪些点应该显示;
|
||||
- 哪些点应该隐藏;
|
||||
- 哪些点需要偏移展开。
|
||||
|
||||
3. 然后拆分图标和文字碰撞
|
||||
- 先保证点图标稳定显示;
|
||||
- 再单独做文字避让。
|
||||
|
||||
4. 最后调整 popup 逻辑
|
||||
- 保证 popup 的碰撞判定和最终可见点保持一致。
|
||||
|
||||
## 9. 涉及文件清单
|
||||
|
||||
本次分析重点涉及以下文件:
|
||||
|
||||
- `src/components/gis/GisView.vue`
|
||||
- `src/components/gis/map.class.ts`
|
||||
- `src/components/gis/map.ol.ts`
|
||||
- `src/components/gis/ol/point-layer-manager.ts`
|
||||
- `src/components/gis/ol/popup-manager.ts`
|
||||
- `src/utils/leaflet/leaflet.inflatable-markers-group.js`
|
||||
- `src/components/gis/map.leaflet.ts`
|
||||
- `package.json`
|
||||
|
||||
## 10. 当前结论
|
||||
|
||||
当前地图问题可以归纳为两点:
|
||||
|
||||
1. 现在的 OpenLayers 主链路并没有真正使用旧 Leaflet 的抽吸机制;
|
||||
2. 当前点图标和文字被作为一个整体参与 declutter,所以文字碰撞时会连点一起隐藏。
|
||||
|
||||
所以后续如果要改,方向不应该只是“调避让参数”,而应该是:
|
||||
|
||||
- 增加近邻点分阶段显示规则;
|
||||
- 增加主动抽吸/偏移布局;
|
||||
- 把图标和文字拆成可独立控制的渲染单元;
|
||||
- 同步修正 popup 的碰撞判断。
|
||||
|
||||
在这个基础上,再进入代码修改会更稳。
|
||||
316
frontend-sjgl/docs/地图模块-抽吸规则与参数说明.md
Normal file
@ -0,0 +1,316 @@
|
||||
# 地图模块-抽吸规则与参数说明
|
||||
|
||||
## 1. 文档目的
|
||||
|
||||
本文档用于记录当前地图点位“抽吸”功能的现行实现、默认参数、分层级显示规则和后续调参方式。
|
||||
本文件描述的是**当前已经落地并验证通过**的规则,适合作为后续维护和继续调参的依据。
|
||||
|
||||
相关文档:
|
||||
|
||||
- `docs/地图模块-详细说明.md`:地图整体架构说明
|
||||
- `docs/地图模块-OpenLayers抽吸与碰撞分析.md`:问题成因与改造分析
|
||||
|
||||
## 2. 当前实现范围
|
||||
|
||||
当前抽吸逻辑运行在 OpenLayers 主链路中,核心文件如下:
|
||||
|
||||
1. `src/modules/map/domain/nearby-point-rules.ts`
|
||||
2. `src/store/modules/map.ts`
|
||||
3. `src/components/gis/map.ol.ts`
|
||||
4. `src/components/gis/ol/point-layer-manager.ts`
|
||||
|
||||
各文件职责:
|
||||
|
||||
- `nearby-point-rules.ts`
|
||||
- 近邻点规则入口
|
||||
- 自动识别配置入口
|
||||
- 近邻点运行时元数据挂载
|
||||
- `map.ts`
|
||||
- 点位数据加载完成后,统一触发近邻点分组和元数据写回
|
||||
- `map.ol.ts`
|
||||
- 决定某个点在当前缩放级别是否显示
|
||||
- 决定文字是否允许显示
|
||||
- 承担图标与文字的手工碰撞控制
|
||||
- `point-layer-manager.ts`
|
||||
- 负责展开阶段的几何偏移
|
||||
- 负责把同组点位按扇形/环形布局散开
|
||||
|
||||
## 3. 当前抽吸规则
|
||||
|
||||
### 3.1 近邻点自动识别
|
||||
|
||||
当前采用自动识别近邻点,不再靠固定站名手工枚举。
|
||||
|
||||
识别原则:
|
||||
|
||||
- 只在同一 `layerKey` 内做近邻识别
|
||||
- 按点位空间距离自动聚组
|
||||
- 满足最小组大小后,才认为是近邻组
|
||||
- 组内自动生成显示优先级 `priority`
|
||||
|
||||
这样做的目的:
|
||||
|
||||
- 避免跨图层混组
|
||||
- 避免后续新增点位还要手工补名字
|
||||
- 让抽吸能力可以覆盖整批业务点
|
||||
|
||||
### 3.2 分层级显示规则
|
||||
|
||||
当前显示规则以 `replaceAtZoom` 和 `expandAtZoom` 为核心:
|
||||
|
||||
1. `zoom < replaceAtZoom`
|
||||
- 只显示组内主点
|
||||
- 即 `priority = 1`
|
||||
2. `replaceAtZoom <= zoom < expandAtZoom`
|
||||
- 显示组内前两个点
|
||||
- 即 `priority <= 2`
|
||||
- 当前这样设计是为了避免主点在放大过程中突然消失
|
||||
3. `zoom >= expandAtZoom`
|
||||
- 同组点全部显示
|
||||
- 同时进入展开布局阶段
|
||||
|
||||
补充规则:
|
||||
|
||||
- 如果某个点配置了 `showZoomMin` 或 `showZoomMax`,则先受这两个值约束
|
||||
- 没有进入近邻组的点,不受抽吸规则影响
|
||||
|
||||
### 3.3 文字显示规则
|
||||
|
||||
当前文字显示必须依赖点位显示。
|
||||
|
||||
也就是说:
|
||||
|
||||
- 点不显示,文字一定不显示
|
||||
- 点显示后,文字还要继续通过碰撞判断才会显示
|
||||
|
||||
当前文字碰撞规则:
|
||||
|
||||
- 文字要避让已保留的图标占位盒
|
||||
- 文字要避让已保留的其他文字
|
||||
- 图标与文字不再分别交给 OpenLayers 的 `declutter` 自动处理
|
||||
- 当前走的是项目内的手工碰撞控制
|
||||
|
||||
## 4. 当前默认参数
|
||||
|
||||
当前默认参数集中维护在:
|
||||
|
||||
- `src/modules/map/domain/nearby-point-rules.ts`
|
||||
|
||||
当前采用统一配置对象:
|
||||
|
||||
```ts
|
||||
type NearbyPointConfig = {
|
||||
autoRule: NearbyPointAutoRule;
|
||||
layoutRule: NearbyPointLayoutRule;
|
||||
densityDisplayRules: NearbyPointDensityDisplayRule[];
|
||||
};
|
||||
```
|
||||
|
||||
其中:
|
||||
|
||||
- `autoRule`:控制近邻点自动识别、缩放切换和基础展开半径
|
||||
- `layoutRule`:控制展开阶段的单圈容量、扇形角度和外圈间距
|
||||
- `densityDisplayRules`:控制 `distance` 密度分档在不同缩放级别的基础显示资格
|
||||
|
||||
### 4.1 自动识别与缩放阶段参数
|
||||
|
||||
当前值如下:
|
||||
|
||||
| 参数 | 当前值 | 作用 |
|
||||
|---|---:|---|
|
||||
| `distanceThresholdMeters` | `9000` | 近邻点自动识别距离阈值 |
|
||||
| `replaceAtZoom` | `10.5` | 进入“主点 + 次点”阶段的缩放级别 |
|
||||
| `expandAtZoom` | `12.2` | 进入“全部显示并展开”阶段的缩放级别 |
|
||||
| `expandOffsetPx` | `48` | 第一圈展开的基础偏移半径 |
|
||||
| `angleStepDeg` | `55` | 默认角度步长参考值 |
|
||||
| `minGroupSize` | `2` | 最小成组数量 |
|
||||
|
||||
### 4.2 展开布局参数
|
||||
|
||||
当前值如下:
|
||||
|
||||
| 参数 | 当前值 | 作用 |
|
||||
|---|---:|---|
|
||||
| `ringSize` | `5` | 单圈最多容纳的次点数量 |
|
||||
| `fanAngleForTwoDeg` | `110` | 单圈剩余 `2` 个点时的扇形总角度 |
|
||||
| `fanAngleForFourDeg` | `150` | 单圈剩余 `3` 到 `4` 个点时的扇形总角度 |
|
||||
| `fanAngleForManyDeg` | `180` | 单圈剩余 `5` 个及以上点时的扇形总角度 |
|
||||
| `ringGapPx` | `22` | 外圈最小增量半径 |
|
||||
| `ringGapFactor` | `0.85` | 外圈相对基础半径的增量系数 |
|
||||
|
||||
### 4.3 密度分档显示参数
|
||||
|
||||
这里的 `distance` 不是物理距离,而是点位密度分档值。
|
||||
数值越大表示越稀疏,越早参与显示候选;数值越小表示越密集,需要更高缩放级别才参与显示。
|
||||
|
||||
当前值如下:
|
||||
|
||||
| `minDensityValue` | `minZoom` | 作用 |
|
||||
|---:|---:|---|
|
||||
| `1500000` | `0` | 很稀疏的点,从小缩放级别就可参与显示 |
|
||||
| `800000` | `6.1` | 稍密集的点,从中低缩放开始参与显示 |
|
||||
| `400000` | `8.1` | 中密度点,需要进一步放大 |
|
||||
| `50000` | `10.6` | 高密度点,需要较高缩放级别 |
|
||||
| `0` | `12.2` | 极密集点,只有更高缩放才进入候选 |
|
||||
|
||||
## 5. 当前展开布局
|
||||
|
||||
展开阶段由 `point-layer-manager.ts` 控制。
|
||||
|
||||
### 5.1 布局特点
|
||||
|
||||
当前布局不是简单把点随机散开,而是按以下方式处理:
|
||||
|
||||
- 主点保留原位置
|
||||
- 同组其他点围绕主点展开
|
||||
- 展开方向优先偏下方
|
||||
- 单圈数量由 `ringSize` 控制
|
||||
- 点数较多时进入第二圈
|
||||
- 第二圈半径按 `ringGapPx` 和 `ringGapFactor` 继续增大,避免继续叠在一起
|
||||
|
||||
### 5.2 为什么优先向下展开
|
||||
|
||||
当前优先向下展开,主要是为了:
|
||||
|
||||
- 尽量给上方文字留空间
|
||||
- 降低文字压住上方点的概率
|
||||
- 让地图上的抽吸形态更稳定
|
||||
|
||||
## 6. 当前实现的几个关键约束
|
||||
|
||||
### 6.1 不使用淡入淡出动画
|
||||
|
||||
目前已移除点和文字的淡入淡出动画。
|
||||
|
||||
原因:
|
||||
|
||||
- 抽吸状态切换和动画叠加时,容易让点和文字出现闪烁
|
||||
- 会干扰对“当前到底该不该显示”的判断
|
||||
|
||||
当前阶段优先保证:
|
||||
|
||||
- 显示规则稳定
|
||||
- 点和文字状态一致
|
||||
- 放大缩小时不出现明显错位
|
||||
|
||||
### 6.2 不再依赖 OL 的自动 declutter 决定图标命运
|
||||
|
||||
当前图标和文字都设置为 `declutterMode: 'none'`,由项目内逻辑统一控制。
|
||||
|
||||
这样做的原因:
|
||||
|
||||
- 避免图标和文字落在两套碰撞体系里
|
||||
- 避免出现“文字先出来、点没出来”
|
||||
- 避免文字压住其他点却仍然显示
|
||||
|
||||
## 7. 常见现象与调参建议
|
||||
|
||||
### 7.1 成组太少
|
||||
|
||||
表现:
|
||||
|
||||
- 相近点仍然容易互相盖住
|
||||
- 进入展开前看起来还是压在一起
|
||||
|
||||
优先调整:
|
||||
|
||||
- 增大 `distanceThresholdMeters`
|
||||
|
||||
### 7.2 成组太多
|
||||
|
||||
表现:
|
||||
|
||||
- 距离并不算近的点也被当成一组
|
||||
- 放大后过早进入抽吸关系
|
||||
|
||||
优先调整:
|
||||
|
||||
- 减小 `distanceThresholdMeters`
|
||||
|
||||
### 7.3 展开太晚
|
||||
|
||||
表现:
|
||||
|
||||
- 放大到较深层级前仍然挤在一起
|
||||
|
||||
优先调整:
|
||||
|
||||
- 减小 `expandAtZoom`
|
||||
|
||||
### 7.4 展开太早
|
||||
|
||||
表现:
|
||||
|
||||
- 中等缩放时地图上就出现较明显散开效果
|
||||
|
||||
优先调整:
|
||||
|
||||
- 增大 `expandAtZoom`
|
||||
|
||||
### 7.5 展开后间距不够
|
||||
|
||||
表现:
|
||||
|
||||
- 虽然已经展开,但图标还是比较挤
|
||||
|
||||
优先调整:
|
||||
|
||||
- 增大 `expandOffsetPx`
|
||||
- 或增大 `ringGapPx`
|
||||
- 或增大 `ringGapFactor`
|
||||
|
||||
### 7.6 单圈散开角度不合适
|
||||
|
||||
表现:
|
||||
|
||||
- 次点虽然已经展开,但仍然集中在一侧
|
||||
- 或者扇形过大,展开形态显得太散
|
||||
|
||||
优先调整:
|
||||
|
||||
- 调整 `fanAngleForTwoDeg`
|
||||
- 调整 `fanAngleForFourDeg`
|
||||
- 调整 `fanAngleForManyDeg`
|
||||
|
||||
### 7.7 主点在放大过程中突然消失
|
||||
|
||||
当前已经通过 `replaceAtZoom <= zoom < expandAtZoom` 阶段显示 `priority <= 2` 进行修正。
|
||||
如果后续又出现类似现象,优先检查:
|
||||
|
||||
- `map.ol.ts` 中 `shouldRenderNearbyFeature()` 的阶段逻辑
|
||||
- 是否误改成只显示 `priority = 2`
|
||||
|
||||
### 7.8 明明周围看起来空,文字还是不显示
|
||||
|
||||
优先检查:
|
||||
|
||||
- 图标碰撞盒是否过大
|
||||
- 文字碰撞盒是否过于保守
|
||||
- 候选集是否发生重复统计
|
||||
|
||||
相关代码主要在:
|
||||
|
||||
- `src/components/gis/map.ol.ts`
|
||||
|
||||
## 8. 后续维护建议
|
||||
|
||||
建议后续继续保持以下约定:
|
||||
|
||||
1. 抽吸参数继续统一放在 `nearby-point-rules.ts`
|
||||
2. 显示决策继续集中在 `map.ol.ts`
|
||||
3. 几何偏移继续集中在 `point-layer-manager.ts`
|
||||
4. 后续调参优先改 `DEFAULT_NEARBY_POINT_CONFIG`,不要直接把数值散落回业务代码
|
||||
5. 如果继续加动画,必须放在抽吸状态机完全稳定之后
|
||||
6. 如果继续优化 popup,也要同步遵循“点先于文字”的显示原则
|
||||
|
||||
## 9. 当前结论
|
||||
|
||||
当前这版抽吸实现已经形成了比较稳定的主线:
|
||||
|
||||
- 自动识别近邻点
|
||||
- 统一缩放阶段显示规则
|
||||
- 展开阶段几何偏移
|
||||
- 文字依赖点显示
|
||||
- 文字避让图标与文字
|
||||
|
||||
后续如果继续调优,建议先从参数层开始,不要先动主逻辑结构。
|
||||
621
frontend-sjgl/docs/地图模块-详细说明.md
Normal file
@ -0,0 +1,621 @@
|
||||
# 地图模块-详细说明
|
||||
|
||||
## 1. 文档目的
|
||||
|
||||
本文档用于说明当前地图模块的真实运行结构、初始化时序、图层与图例联动、点位渲染规则、筛选与缩放行为,以及近期已经落地的关键约束。
|
||||
|
||||
本文档描述的是“当前可运行版本”的现状,不展开抽吸参数细节与专项问题分析。相关补充文档如下:
|
||||
|
||||
- `docs/地图模块-抽吸规则与参数说明.md`
|
||||
- `docs/地图模块-OpenLayers抽吸与碰撞分析.md`
|
||||
|
||||
## 2. 当前技术栈
|
||||
|
||||
- 前端框架:Vue 3 + TypeScript + Ant Design Vue
|
||||
- 状态管理:Pinia
|
||||
- 2D 地图引擎:OpenLayers 10.8.0
|
||||
- 3D 地图引擎:Cesium
|
||||
- 地图服务:GeoServer / WMTS / XYZ
|
||||
- 运行模式:后台配置驱动 + 前台运行时编排
|
||||
|
||||
说明:
|
||||
|
||||
- 当前 2D 主链路已经完全围绕 OpenLayers 组织。
|
||||
- 项目中仍保留 Leaflet 相关依赖和旧代码,但不是当前主执行路径。
|
||||
|
||||
## 3. 模块分层
|
||||
|
||||
当前地图模块可以按 6 层理解:
|
||||
|
||||
1. 页面入口层
|
||||
2. 应用编排层
|
||||
3. 地图能力门面层
|
||||
4. 地图引擎执行层
|
||||
5. Store 运行态层
|
||||
6. 前台交互组件层
|
||||
|
||||
对应核心文件如下:
|
||||
|
||||
- 页面入口层
|
||||
- `src/components/gis/GisView.vue`
|
||||
- 应用编排层
|
||||
- `src/modules/map/application/map-orchestrator.ts`
|
||||
- 地图能力门面层
|
||||
- `src/components/gis/map.class.ts`
|
||||
- 地图引擎执行层
|
||||
- `src/components/gis/map.ol.ts`
|
||||
- `src/components/gis/map.cesium.ts`
|
||||
- `src/components/gis/ol/point-layer-manager.ts`
|
||||
- `src/components/gis/ol/popup-manager.ts`
|
||||
- Store 运行态层
|
||||
- `src/store/modules/map.ts`
|
||||
- `src/modules/map/stores/map-config.store.ts`
|
||||
- `src/modules/map/stores/map-data.store.ts`
|
||||
- `src/modules/map/stores/map-view.store.ts`
|
||||
- 前台交互组件层
|
||||
- `src/components/mapLegend/index.vue`
|
||||
- `src/components/mapFilter/index.vue`
|
||||
- `src/components/mapController/index.vue`
|
||||
- `src/components/mapController/LayerController.vue`
|
||||
- `src/components/BaseLayerSwitcher/index.vue`
|
||||
|
||||
## 4. 整体原则
|
||||
|
||||
当前地图模块遵循以下几个运行原则:
|
||||
|
||||
### 4.1 地图容器全局常驻
|
||||
|
||||
地图由 `GisView.vue` 常驻挂载,不会随着菜单切换被销毁重建。页面切换本质上是:
|
||||
|
||||
- 重新计算 `pageKey`
|
||||
- 重新加载该页图层配置和图例配置
|
||||
- 用新的运行态覆盖旧页面显示内容
|
||||
|
||||
### 4.2 配置驱动
|
||||
|
||||
前端不把全部图层和图例硬编码死,而是依赖后端返回的:
|
||||
|
||||
- 图层树配置
|
||||
- 图例配置
|
||||
- 页面级图例配置
|
||||
- 各业务点位接口数据
|
||||
|
||||
### 4.3 运行态绝对优先
|
||||
|
||||
初始化默认值只在第一次派生时生效;一旦进入运行态,后续图层勾选、图例勾选、筛选器切换,都必须以当前用户操作后的状态为准,不能在加载完成后回退到默认状态。
|
||||
|
||||
## 5. 页面入口层
|
||||
|
||||
### 5.1 `GisView.vue`
|
||||
|
||||
`GisView.vue` 的职责主要是:
|
||||
|
||||
- 提供地图容器 `#mapContainer`
|
||||
- 提供 popup 挂载容器
|
||||
- 挂载图例、筛选器、控制器、底图切换器
|
||||
- 根据路由计算 `pageKey`
|
||||
- 在挂载时调用 `mapOrchestrator.mountView()`
|
||||
- 在页面切换时交给编排器重载页面
|
||||
|
||||
当前页面层已经不再直接承载复杂业务逻辑,复杂链路都收敛到了编排器和 Store。
|
||||
|
||||
## 6. 应用编排层
|
||||
|
||||
### 6.1 `map-orchestrator.ts` 的职责
|
||||
|
||||
`map-orchestrator.ts` 是当前地图业务的总调度中心,主要负责:
|
||||
|
||||
- 初始化地图壳与 popup
|
||||
- 加载页面图层配置和图例配置
|
||||
- 初始化 GIS 基础图层
|
||||
- 触发点位图层加载
|
||||
- 管理缩放监听和基地切换监听
|
||||
- 处理图层树勾选
|
||||
- 处理图例勾选
|
||||
- 处理时间筛选、容量筛选、搜索定位
|
||||
- 处理水电开发菜单下的缩放联动图层
|
||||
|
||||
### 6.2 页面初始化链路
|
||||
|
||||
当前初始化顺序如下:
|
||||
|
||||
1. `GisView.vue` 调用 `mapOrchestrator.mountView()`
|
||||
2. `MapClass.init()` 初始化地图实例
|
||||
3. 页面级 popup 容器挂到地图实例
|
||||
4. 绑定缩放监听和基地监听
|
||||
5. 并行请求图层树配置与图例配置
|
||||
6. 图例接口先返回时,立即生成图例运行态
|
||||
7. 图层树接口返回后,生成默认勾选图层并初始化 GIS 基础图层
|
||||
8. 再按图层配置批量加载点位数据
|
||||
|
||||
这里有两个当前已落地的关键时序调整:
|
||||
|
||||
- 图例转圈只跟图例接口绑定,不再等待所有锚点接口完成。
|
||||
- 筛选器数据会随着已加载图层逐步出现,不再必须等全量点位接口结束。
|
||||
|
||||
### 6.3 页面切换
|
||||
|
||||
页面切换时地图不销毁,只重载当前页面的:
|
||||
|
||||
- 图层树配置
|
||||
- 图例配置
|
||||
- 点位数据
|
||||
- 当前页面的默认运行态
|
||||
|
||||
如果仍处于同一个 `pageKey` 且用户之前修改过勾选态,会尽量复用当前运行态,而不是重新回放默认勾选。
|
||||
|
||||
### 6.4 缩放联动
|
||||
|
||||
当前编排层主要有两类缩放联动:
|
||||
|
||||
- `eng_point` 缩放联动
|
||||
- 大型电站始终允许显示
|
||||
- 中型电站仅在 `zoom > 7.5` 时进入显示候选
|
||||
- 水电开发菜单动态图层联动
|
||||
- `HYDRO_DYNAMIC_LAYER_KEYS` 在缩放跨越阈值时参与加载与显隐编排
|
||||
|
||||
## 7. 地图能力门面层
|
||||
|
||||
### 7.1 `map.class.ts`
|
||||
|
||||
`MapClass` 是地图能力统一门面,屏蔽 2D / 3D 引擎差异,对外暴露统一方法。
|
||||
|
||||
当前常用能力包括:
|
||||
|
||||
- `init()`
|
||||
- `initPopupOverlay()`
|
||||
- `addBaseDataLayer()`
|
||||
- `addInitDataLayer()`
|
||||
- `mdLayerTreeShowOrHidden()`
|
||||
- `controlBaseLayerTreeShowAndHidden()`
|
||||
- `setLegendPointVisible()`
|
||||
- `hasLayer()`
|
||||
- `hasBaseLayer()`
|
||||
- `removePointLayer()`
|
||||
- `flyTopanto()`
|
||||
- `switchView()`
|
||||
|
||||
当前业务主执行层仍然是 `MapOl`。
|
||||
|
||||
## 8. 地图引擎执行层
|
||||
|
||||
### 8.1 OpenLayers 主执行层
|
||||
|
||||
`map.ol.ts` 负责 OpenLayers 地图的实际渲染与交互,是当前 2D 地图主执行文件。
|
||||
|
||||
当前承担的核心能力包括:
|
||||
|
||||
- 地图实例初始化
|
||||
- 底图与 GIS 图层管理
|
||||
- 点位图层渲染
|
||||
- 图标与文字样式生成
|
||||
- hover popup 与批量 popup
|
||||
- 基地范围裁切
|
||||
- 高缩放交互
|
||||
- 测量、截图、飞行定位等基础地图能力
|
||||
|
||||
### 8.2 Cesium 执行层
|
||||
|
||||
`map.cesium.ts` 目前更多是保留 3D 入口和部分基础能力,复杂业务点位与碰撞规则并未与 OpenLayers 完全对齐。
|
||||
|
||||
结论上,当前真实业务规则仍然以 OpenLayers 链路为准。
|
||||
|
||||
## 9. Store 分层
|
||||
|
||||
### 9.1 `map-config.store.ts`
|
||||
|
||||
负责配置态数据:
|
||||
|
||||
- 图层树配置
|
||||
- 图层配置索引
|
||||
- 全量原始图例配置
|
||||
- 图例索引
|
||||
- 页面级图例配置
|
||||
- 配置接口加载状态
|
||||
|
||||
当前这里拆分出了两个加载态:
|
||||
|
||||
- `configLoading`
|
||||
- `legendLoading`
|
||||
|
||||
其中 `legendLoading` 单独控制图例转圈。
|
||||
|
||||
### 9.2 `map-data.store.ts`
|
||||
|
||||
负责数据态:
|
||||
|
||||
- `pointData`
|
||||
- `pointDataCache`
|
||||
- `layerLoadState`
|
||||
- 地图整体 `loading`
|
||||
|
||||
这里的关键设计是:
|
||||
|
||||
- 每个点图层有独立缓存
|
||||
- `pointData` 是由缓存合并出来的运行态数据
|
||||
- 单个图层命中缓存或接口返回后,就会立即回填 `pointData`
|
||||
|
||||
因此当前搜索筛选下拉已经支持“渐进可用”,不再只能等全部接口结束。
|
||||
|
||||
### 9.3 `map-view.store.ts`
|
||||
|
||||
负责视图运行态:
|
||||
|
||||
- 当前勾选图层 `checkedLayerKeys`
|
||||
- 图例勾选状态 `legendCheckedState`
|
||||
- 搜索时间范围
|
||||
- 当前基地
|
||||
- 当前缩放级别
|
||||
|
||||
### 9.4 `src/store/modules/map.ts`
|
||||
|
||||
这是当前地图运行逻辑最重的 Store,负责串联配置、缓存和地图实例。
|
||||
|
||||
主要职责包括:
|
||||
|
||||
- 生成图例运行态
|
||||
- 批量加载点位数据
|
||||
- 控制图层显隐
|
||||
- 控制图例显隐
|
||||
- 管理请求缓存与并发加载
|
||||
- 刷新点图层显示数据
|
||||
- 处理 `eng_point` 的显示过滤
|
||||
- 在全量点位准备完成后挂载近邻点元数据
|
||||
|
||||
## 10. 图层分类
|
||||
|
||||
当前地图里的图层大体可以分成三类:
|
||||
|
||||
### 10.1 `GISMap`
|
||||
|
||||
这类图层对应 GIS 基础图层或专题底图,由 `addBaseDataLayer()` 加载到 `layerRegistry`。
|
||||
|
||||
当前已补充的规则:
|
||||
|
||||
- 勾选 `GISMap` 时,不能只做显示/隐藏。
|
||||
- 如果地图实例中不存在该图层,需要先重新加载,再显示。
|
||||
|
||||
### 10.2 点位图层
|
||||
|
||||
这类图层由接口返回锚点数据,最终进入 `PointLayerManager` 维护的 `VectorLayer`。
|
||||
|
||||
### 10.3 其他专题图层
|
||||
|
||||
例如梯级流域、区域裁切辅助层等,这些更多由 `map.ol.ts` 单独控制。
|
||||
|
||||
## 11. 图层数据加载机制
|
||||
|
||||
### 11.1 配置与数据分离
|
||||
|
||||
当前初始化时,配置加载与点位数据加载是两条链:
|
||||
|
||||
- 图层树配置决定有哪些层、哪些默认勾选
|
||||
- 图例配置决定图例结构和图例项元数据
|
||||
- 点位数据接口决定地图上实际锚点内容
|
||||
|
||||
### 11.2 加载顺序
|
||||
|
||||
`loadAllLayerData()` 的主要逻辑是:
|
||||
|
||||
1. 先收集所有带 URL 的图层
|
||||
2. 把默认勾选图层作为高优先级任务
|
||||
3. 收集完成后全量并发加载,不再按 4 个一组分批发起
|
||||
4. 每个图层完成后立即写入缓存
|
||||
5. 每个图层命中缓存或返回成功后,立即增量更新 `pointData`
|
||||
6. 全部图层结束后,再统一:
|
||||
- 回填每层原始数据
|
||||
- 挂载近邻点运行时元数据
|
||||
- 刷新各图层显示数据
|
||||
- 用最新运行态收尾
|
||||
|
||||
### 11.3 初始化阶段的图例绝对性
|
||||
|
||||
当前已修复一个关键问题:
|
||||
|
||||
- 图例虽然可能在界面上还在 loading
|
||||
- 但只要图例配置已经返回,默认隐藏的图例项在点位首批入图时就必须生效
|
||||
|
||||
也就是说,现在不会再出现:
|
||||
|
||||
- loading 过程中先显示默认隐藏点
|
||||
- loading 结束后才消失
|
||||
|
||||
## 12. 图例机制
|
||||
|
||||
### 12.1 图例来源
|
||||
|
||||
图例运行态由以下数据共同决定:
|
||||
|
||||
- 原始全量图例配置
|
||||
- 当前页面图例配置
|
||||
- 当前已勾选图层
|
||||
- 当前图例勾选状态
|
||||
|
||||
### 12.2 图例派生
|
||||
|
||||
图例最终显示的是 `legendDataSelected`,而不是全量图例。
|
||||
|
||||
派生逻辑核心原则如下:
|
||||
|
||||
- 只有当前勾选图层对应的图例项才进入页面图例
|
||||
- 图例勾选状态是运行态绝对值
|
||||
- 环保设施分组有单独规则
|
||||
|
||||
### 12.3 图例加载时机
|
||||
|
||||
当前图例面板的 loading 只跟图例接口绑定:
|
||||
|
||||
- 图例接口返回后立即停转
|
||||
- 图例内容在图层默认勾选同步后立即派生
|
||||
- 不再等待所有锚点接口完成
|
||||
|
||||
## 13. 筛选器机制
|
||||
|
||||
### 13.1 `MapFilter` 的职责
|
||||
|
||||
筛选器当前包含以下能力:
|
||||
|
||||
- 时间范围筛选
|
||||
- 装机容量筛选
|
||||
- 搜索定位
|
||||
- 个别页面的专题筛选项
|
||||
|
||||
### 13.2 搜索下拉来源
|
||||
|
||||
搜索下拉使用 `mapDataStore.pointData` 作为数据源。
|
||||
|
||||
当前行为已经调整为:
|
||||
|
||||
- 某个图层一旦命中缓存,筛选器即可出现该图层点位
|
||||
- 某个图层接口一旦返回成功,筛选器也会立即出现该图层点位
|
||||
|
||||
因此筛选器当前是“渐进展示”,而不是“全量完成后一次性展示”。
|
||||
|
||||
### 13.3 装机容量筛选
|
||||
|
||||
装机容量筛选针对 `eng_point` 图层,当前规则如下:
|
||||
|
||||
- `all`
|
||||
- 恢复大型与中型图例
|
||||
- `large_eng_built`
|
||||
- 只保留 `large_eng_` 前缀相关图例
|
||||
- 地图上只显示大型电站点位
|
||||
- `mid_eng_built`
|
||||
- 只保留 `mid_eng_` 前缀相关图例
|
||||
- 地图上只显示中型电站点位
|
||||
|
||||
当前容量切换不再只是影响筛选器本地下拉,而是会同步驱动:
|
||||
|
||||
- 图例运行态
|
||||
- `eng_point` 点位显示
|
||||
|
||||
## 14. `eng_point` 专项规则
|
||||
|
||||
`eng_point` 是当前地图模块中的特殊图层,存在独立显示规则。
|
||||
|
||||
### 14.1 缩放规则
|
||||
|
||||
在数据入图阶段就生效:
|
||||
|
||||
- 大型电站始终允许显示
|
||||
- 中型电站仅在 `zoom > 7.5` 时允许进入显示候选
|
||||
|
||||
这不是单纯的图例控制,而是点位入图时的过滤逻辑。
|
||||
|
||||
### 14.2 图例规则
|
||||
|
||||
点位入图之后,仍然必须再经过图例运行态控制:
|
||||
|
||||
- 允许入图,不等于最终可见
|
||||
- 只要图例勾选为隐藏,该类点位就必须隐藏
|
||||
|
||||
### 14.3 容量筛选规则
|
||||
|
||||
装机容量下拉会进一步批量控制 `eng_point` 的图例项,使图例与点位同步切换。
|
||||
|
||||
## 15. 点位显示裁决链
|
||||
|
||||
当前点位最终是否显示,至少会经过以下几层判断:
|
||||
|
||||
1. 图层是否勾选
|
||||
2. 图例是否勾选
|
||||
3. 基地范围是否允许
|
||||
4. `eng_point` 缩放过滤是否通过
|
||||
5. `distance` 密度分档是否通过
|
||||
6. 近邻点显示阶段是否通过
|
||||
7. 图标是否已加载完成
|
||||
8. 当前缩放下是否进入碰撞控制
|
||||
|
||||
这几层不是互斥关系,而是叠加裁决。
|
||||
|
||||
## 16. 点位渲染与样式
|
||||
|
||||
### 16.1 基础样式
|
||||
|
||||
当前点位渲染包括:
|
||||
|
||||
- 图标
|
||||
- 文字标签
|
||||
- 标签换行与截断
|
||||
- 缩放相关的图标与文字样式变化
|
||||
|
||||
### 16.2 图标加载约束
|
||||
|
||||
当前已经补充图标加载状态缓存:
|
||||
|
||||
- 图标未加载完成时,不显示该点
|
||||
- 图标未加载完成时,文字也不先显示
|
||||
- 图标未加载完成时,不参与碰撞候选
|
||||
|
||||
这样可以避免“文字先出来、图标还是空的”的问题。
|
||||
|
||||
## 17. 抽吸、密度与碰撞
|
||||
|
||||
### 17.1 专项文档
|
||||
|
||||
抽吸与密度分档的详细参数请查看:
|
||||
|
||||
- `docs/地图模块-抽吸规则与参数说明.md`
|
||||
|
||||
### 17.2 当前裁决顺序
|
||||
|
||||
当前点位显示顺序可以理解为:
|
||||
|
||||
1. 密度分档
|
||||
2. 近邻抽吸
|
||||
3. 图标碰撞
|
||||
4. 文字碰撞
|
||||
|
||||
补充约束:
|
||||
|
||||
- 只有满足可见性条件的点,才能进入碰撞候选集
|
||||
- 被图例或缩放过滤掉的点,不能再去占用碰撞资格
|
||||
- 视图内无近邻的孤立点允许局部放行
|
||||
|
||||
### 17.3 高缩放特例
|
||||
|
||||
当前在高缩放层级 `zoom >= 15` 时,行为与中低缩放不同:
|
||||
|
||||
- 只处理视口内点位
|
||||
- 点与文字不再做碰撞淘汰
|
||||
- 视口内符合基础显示条件的点和文字全部显示
|
||||
- 同时进入批量 popup 模式
|
||||
|
||||
这条规则的目标是:
|
||||
|
||||
- 保证深度放大后信息完整可见
|
||||
- 避免高缩放下还因为碰撞把点或文字压掉
|
||||
|
||||
## 18. Popup 机制
|
||||
|
||||
### 18.1 两类 popup
|
||||
|
||||
当前 popup 分成两类:
|
||||
|
||||
- hover popup
|
||||
- batch popup
|
||||
|
||||
### 18.2 hover popup
|
||||
|
||||
鼠标悬停时由 `pointermove` 驱动,只在非 batch popup 模式下显示。
|
||||
|
||||
### 18.3 batch popup
|
||||
|
||||
在 `zoom >= 15` 时进入批量 popup 模式:
|
||||
|
||||
- 只基于当前视口内点位
|
||||
- 拖动地图时持续刷新
|
||||
- 但通过 `requestAnimationFrame` 做节流
|
||||
- `moveend` 后立即再做一次强制刷新
|
||||
|
||||
当前这样做是为了兼顾两件事:
|
||||
|
||||
- 保留“拖动时 popup 跟着更新”的原交互
|
||||
- 避免拖动过程中每个事件都重建整批 DOM
|
||||
|
||||
### 18.4 惯性平移已关闭
|
||||
|
||||
当前地图拖动已经关闭 OpenLayers 默认惯性平移:
|
||||
|
||||
- 普通拖动仍然保留
|
||||
- 松手后不再继续滑动一小段
|
||||
|
||||
这样可以减少高缩放 popup 场景下“松手还轻微位移”的观感问题。
|
||||
|
||||
## 19. 基地与区域过滤
|
||||
|
||||
基地切换是当前地图模块的关键能力之一,主要影响:
|
||||
|
||||
- 地图裁切范围
|
||||
- 当前基地相关点位的可见性
|
||||
- 部分专题图层显示
|
||||
|
||||
整体过程通常是:
|
||||
|
||||
1. 外部基地选择源变化
|
||||
2. 编排器接收到基地 ID
|
||||
3. 地图实例切换基地范围
|
||||
4. 点位更新 `_regionVisible`
|
||||
5. 样式函数按区域可见性决定是否显示
|
||||
|
||||
## 20. 典型交互链路
|
||||
|
||||
### 20.1 图层树勾选
|
||||
|
||||
1. `LayerController` 触发勾选变化
|
||||
2. 编排器归一化图层 key
|
||||
3. `map.ts` 更新运行态图层勾选
|
||||
4. 地图实例更新图层显隐
|
||||
5. 图例重新派生
|
||||
|
||||
补充:
|
||||
|
||||
- `GISMap` 勾选时,如果地图里没有该图层,会先补载,再显示
|
||||
|
||||
### 20.2 图例勾选
|
||||
|
||||
1. 图例组件触发点击
|
||||
2. 编排器转发图例切换
|
||||
3. `map.ts` 更新图例运行态
|
||||
4. 对应点位立即更新显隐
|
||||
5. 图例树同步更新灰态
|
||||
|
||||
### 20.3 筛选器操作
|
||||
|
||||
1. 用户切换时间、容量、搜索等条件
|
||||
2. 编排器接收命令
|
||||
3. 视情况更新视图运行态或重载数据
|
||||
4. 地图实例与图例运行态同步刷新
|
||||
|
||||
### 20.4 缩放操作
|
||||
|
||||
1. OpenLayers 视图触发 `change:resolution`
|
||||
2. 编排器更新当前缩放级别
|
||||
3. 处理 `eng_point` 阈值联动
|
||||
4. 水电开发菜单下处理动态图层联动
|
||||
5. `map.ol.ts` 处理高缩放 popup 与点位显示策略
|
||||
|
||||
## 21. 当前重点文件清单
|
||||
|
||||
- `src/components/gis/GisView.vue`
|
||||
- `src/components/gis/map.class.ts`
|
||||
- `src/components/gis/map.ol.ts`
|
||||
- `src/components/gis/map.cesium.ts`
|
||||
- `src/components/gis/gisUtils.ts`
|
||||
- `src/components/gis/mapurlManage.ts`
|
||||
- `src/components/gis/ol/point-layer-manager.ts`
|
||||
- `src/components/gis/ol/popup-manager.ts`
|
||||
- `src/modules/map/application/map-orchestrator.ts`
|
||||
- `src/modules/map/stores/map-config.store.ts`
|
||||
- `src/modules/map/stores/map-data.store.ts`
|
||||
- `src/modules/map/stores/map-view.store.ts`
|
||||
- `src/store/modules/map.ts`
|
||||
- `src/components/mapLegend/index.vue`
|
||||
- `src/components/mapFilter/index.vue`
|
||||
- `src/components/mapController/index.vue`
|
||||
- `src/components/mapController/LayerController.vue`
|
||||
- `src/components/BaseLayerSwitcher/index.vue`
|
||||
|
||||
## 22. 当前结论
|
||||
|
||||
当前地图模块已经形成比较清晰的主干结构:
|
||||
|
||||
- `GisView` 负责挂载与页面入口
|
||||
- `map-orchestrator` 负责业务编排
|
||||
- `MapClass` 负责能力门面
|
||||
- `MapOl` 负责 2D 主执行
|
||||
- `map.ts + 三个拆分 store` 共同维护配置、数据与视图运行态
|
||||
- 图层树、图例、筛选器、popup、高缩放规则都已经围绕这条主干收口
|
||||
|
||||
相较旧版说明,当前最重要的现状变化有 8 点:
|
||||
|
||||
1. 图例 loading 已与锚点全量加载解耦
|
||||
2. 筛选器数据已支持渐进展示
|
||||
3. 初始化阶段默认隐藏图例项会立即生效
|
||||
4. 运行态勾选不会在 loading 完成后被默认值覆盖
|
||||
5. `eng_point` 有独立的缩放与容量规则
|
||||
6. 高缩放下视口内点和文字全部显示,不再做碰撞淘汰
|
||||
7. batch popup 保留拖动跟随,但增加了节流
|
||||
8. 地图拖动惯性已关闭
|
||||
|
||||
后续如果继续扩展地图功能,建议仍然优先沿着“编排层 + Store 分层 + OpenLayers 执行层”这条主干扩展,不要再把复杂业务回填到页面组件里。
|
||||
1158
frontend-sjgl/docs/地图模块现状与改造方案.md
Normal file
380
frontend-sjgl/docs/地图模块重构实施清单.md
Normal file
@ -0,0 +1,380 @@
|
||||
# 地图模块重构实施清单
|
||||
|
||||
## 1. 使用说明
|
||||
|
||||
本文档是地图模块重构的执行清单,只保留当前已经明确、可以直接落地的实施项。
|
||||
|
||||
以下内容暂不纳入本清单:
|
||||
|
||||
- 仍需进一步讨论的方案;
|
||||
- 依赖后端配合后才能确定的优化项;
|
||||
- 暂未确定收益与改造成本的预研项;
|
||||
- 调试面板、埋点体系、长期性能平台化建设等扩展项。
|
||||
|
||||
执行原则:
|
||||
|
||||
- 先止血,再拆层,再提速;
|
||||
- 每一步都要保证现有业务可用;
|
||||
- 每个阶段结束后都要做功能回归;
|
||||
- 不在同一阶段同时改动 UI、Store、地图渲染层的大块逻辑。
|
||||
|
||||
---
|
||||
|
||||
## 2. 本轮重构目标
|
||||
|
||||
本轮只完成以下确定目标:
|
||||
|
||||
- 收口当前明显缺陷和遗留代码;
|
||||
- 建立基础类型和索引;
|
||||
- 将分散在组件中的核心业务规则收口;
|
||||
- 拆分地图 Store,建立更清晰的数据职责;
|
||||
- 抽离统一编排层;
|
||||
- 拆分 `map.ol.ts` 的核心管理职责;
|
||||
- 保证图层树、图例、锚点显隐链路更清晰;
|
||||
- 为后续继续重构预留稳定结构。
|
||||
|
||||
---
|
||||
|
||||
## 3. 阶段一:现状收口与问题修复
|
||||
|
||||
## 3.1 清理明显遗留问题
|
||||
|
||||
- [ ] 删除 `map.ol.ts` 中无意义代码和重复日志
|
||||
- [ ] 清理大段失效注释,保留必要说明
|
||||
- [ ] 统一地图相关文件中的临时 `console.log`
|
||||
|
||||
涉及文件:
|
||||
|
||||
- `src/components/gis/map.ol.ts`
|
||||
|
||||
验收标准:
|
||||
|
||||
- 页面可正常编译;
|
||||
- 首次进入地图页面不报错;
|
||||
- 控制台不再出现未定义函数或变量错误;
|
||||
- 默认图层、图例、锚点仍可正常显示。
|
||||
|
||||
## 3.2 补充基础类型定义
|
||||
|
||||
- [ ] 新增地图图层类型定义
|
||||
- [ ] 新增图例结构类型定义
|
||||
- [ ] 新增锚点数据类型定义
|
||||
- [ ] 新增筛选参数类型定义
|
||||
- [ ] 为 `map.ts`、`map.class.ts`、`map.ol.ts` 替换第一批高频 `any`
|
||||
|
||||
建议新增文件:
|
||||
|
||||
- `src/modules/map/types/map-layer.ts`
|
||||
- `src/modules/map/types/map-legend.ts`
|
||||
- `src/modules/map/types/map-point.ts`
|
||||
- `src/modules/map/types/map-filter.ts`
|
||||
|
||||
验收标准:
|
||||
|
||||
- 核心地图模块类型边界可读;
|
||||
- 新增类型后不影响现有运行;
|
||||
- `map.ts`、`map.ol.ts` 中关键方法参数不再全部使用 `any`。
|
||||
|
||||
## 3.3 建立基础索引
|
||||
|
||||
- [x] 建立 `layerByKey` 索引
|
||||
- [x] 建立 `legendByNameEn` 索引
|
||||
- [x] 建立 `legendByLayerCode` 索引
|
||||
- [x] 将 `findLayerByKey()` 的高频调用逐步替换为索引访问
|
||||
- [x] 将图例派生中的重复递归改为“初始化索引 + 增量查询”
|
||||
|
||||
优先改造位置:
|
||||
|
||||
- `src/store/modules/map.ts`
|
||||
|
||||
验收标准:
|
||||
|
||||
- 图层查找和图例查找不再完全依赖全量递归;
|
||||
- 图层勾选、图例切换后响应速度不下降;
|
||||
- 功能表现与现状一致。
|
||||
|
||||
---
|
||||
|
||||
## 4. 阶段二:规则收口
|
||||
|
||||
## 4.1 收口互斥规则
|
||||
|
||||
- [x] 将图层互斥逻辑从 `LayerController.vue` 中移出
|
||||
- [x] 将视频监控站与 AI 视频监控站互斥统一到规则函数
|
||||
- [x] 将环保设施与环保设施在建互斥统一到规则函数
|
||||
- [x] 将珍稀鱼类与沿程鱼类互斥统一到规则函数
|
||||
- [x] 保证互斥规则只有一个入口执行
|
||||
|
||||
建议新增文件:
|
||||
|
||||
- `src/modules/map/domain/map-layer-rules.ts`
|
||||
|
||||
涉及文件:
|
||||
|
||||
- `src/components/mapController/LayerController.vue`
|
||||
- `src/store/modules/map.ts`
|
||||
|
||||
验收标准:
|
||||
|
||||
- 图层树勾选时互斥结果稳定;
|
||||
- 不再同时在组件和 Store 两处维护同一套互斥规则;
|
||||
- 勾选结果、图例结果、地图显示结果保持一致。
|
||||
|
||||
## 4.2 收口图例派生规则
|
||||
|
||||
- [x] 将“图层选中后生成图例”逻辑提炼为独立函数
|
||||
- [x] 将“环保设施图例自动补充”逻辑提炼为独立规则
|
||||
- [x] 分离图例原始结构与图例选中状态
|
||||
- [x] 保证 `legendDataOriginal` 不再被运行态逻辑污染
|
||||
|
||||
建议新增文件:
|
||||
|
||||
- `src/modules/map/domain/legend-deriver.ts`
|
||||
|
||||
涉及文件:
|
||||
|
||||
- `src/store/modules/map.ts`
|
||||
- `src/components/mapLegend/index.vue`
|
||||
|
||||
验收标准:
|
||||
|
||||
- 图例显示仍按当前选中图层正确联动;
|
||||
- 图例点击后锚点显隐正确;
|
||||
- 图例原始结构与运行时状态职责更清晰。
|
||||
|
||||
---
|
||||
|
||||
## 5. 阶段三:拆分 Store
|
||||
|
||||
## 5.1 拆分配置状态
|
||||
|
||||
- [ ] 抽离图层树配置状态
|
||||
- [ ] 抽离图例原始配置状态
|
||||
- [ ] 抽离页面地图配置加载逻辑
|
||||
|
||||
建议新增文件:
|
||||
|
||||
- `src/modules/map/stores/map-config.store.ts`
|
||||
|
||||
当前迁移来源:
|
||||
|
||||
- `src/store/modules/map.ts`
|
||||
- `src/api/map.ts`
|
||||
|
||||
## 5.2 拆分运行状态
|
||||
|
||||
- [ ] 抽离当前选中图层 key
|
||||
- [ ] 抽离当前选中图例 key
|
||||
- [ ] 抽离当前基地、时间范围、缩放级别等运行态
|
||||
- [ ] 统一“当前地图状态”的唯一来源
|
||||
|
||||
建议新增文件:
|
||||
|
||||
- `src/modules/map/stores/map-view.store.ts`
|
||||
|
||||
## 5.3 拆分数据缓存
|
||||
|
||||
- [ ] 抽离锚点缓存
|
||||
- [ ] 抽离图层加载状态
|
||||
- [ ] 抽离锚点合并数据 `pointData`
|
||||
- [ ] 为每个图层维护独立 `loading / loaded / error`
|
||||
|
||||
建议新增文件:
|
||||
|
||||
- `src/modules/map/stores/map-data.store.ts`
|
||||
|
||||
验收标准:
|
||||
|
||||
- 原 `map.ts` 体积明显下降;
|
||||
- 配置、运行态、数据缓存职责分离;
|
||||
- 现有组件仍可通过兼容方式读取数据;
|
||||
- 默认图层、图例、锚点加载不受影响。
|
||||
|
||||
---
|
||||
|
||||
## 6. 阶段四:建立统一编排层
|
||||
|
||||
## 6.1 新增地图编排器
|
||||
|
||||
- [x] 新增地图模块统一编排入口
|
||||
- [x] 将地图初始化流程迁移到编排器
|
||||
- [x] 将图层勾选、图例勾选、基地切换、时间筛选、搜索定位改为统一命令
|
||||
- [x] 收口 `GisView.vue` 中的配置加载与监听联动逻辑
|
||||
|
||||
建议新增文件:
|
||||
|
||||
- `src/modules/map/application/map-orchestrator.ts`
|
||||
|
||||
## 6.2 统一入口命令
|
||||
|
||||
- [x] 定义 `initialize(pageKey)`
|
||||
- [x] 定义 `toggleLayer(layerKey)`
|
||||
- [x] 定义 `toggleLegend(layerKey, legendKey)`
|
||||
- [x] 定义 `changeBaseId(baseId)`
|
||||
- [x] 定义 `changeTimeRange(range)`
|
||||
- [x] 定义 `focusPoint(pointId)`
|
||||
|
||||
涉及文件:
|
||||
|
||||
- `src/components/gis/GisView.vue`
|
||||
- `src/components/mapController/LayerController.vue`
|
||||
- `src/components/mapLegend/index.vue`
|
||||
- `src/components/mapFilter/index.vue`
|
||||
|
||||
验收标准:
|
||||
|
||||
- 地图相关 UI 组件不再直接拼复杂业务逻辑;
|
||||
- 组件交互都通过统一入口触发;
|
||||
- 图层树、图例、筛选的联动链路更容易追踪。
|
||||
|
||||
---
|
||||
|
||||
## 7. 阶段五:拆分 OpenLayers 渲染层
|
||||
|
||||
## 7.1 拆分点图层管理
|
||||
|
||||
- [ ] 从 `map.ol.ts` 中抽离锚点图层创建逻辑
|
||||
- [ ] 从 `map.ol.ts` 中抽离锚点显隐逻辑
|
||||
- [ ] 从 `map.ol.ts` 中抽离图例控制锚点逻辑
|
||||
- [ ] 在点图层管理模块中维护图层注册表
|
||||
|
||||
建议新增文件:
|
||||
|
||||
- `src/components/gis/ol/point-layer-manager.ts`
|
||||
|
||||
当前迁移来源:
|
||||
|
||||
- `src/components/gis/map.ol.ts`
|
||||
|
||||
## 7.2 拆分 Popup 管理
|
||||
|
||||
- [ ] 抽离 `initPopupOverlay()`
|
||||
- [ ] 抽离 `detectFeatureAtPixel()`
|
||||
- [ ] 抽离 `showPopup()`
|
||||
- [ ] 收口 hover 和 click 交互逻辑
|
||||
|
||||
建议新增文件:
|
||||
|
||||
- `src/components/gis/ol/popup-manager.ts`
|
||||
|
||||
## 7.3 拆分区域过滤管理
|
||||
|
||||
- [x] 抽离基地切换后的区域裁切逻辑
|
||||
- [x] 抽离点在面内判断逻辑
|
||||
- [x] 抽离区域外锚点显隐逻辑
|
||||
- [x] 抽离遮罩应用与清理逻辑
|
||||
|
||||
建议新增文件:
|
||||
|
||||
- `src/components/gis/ol/region-mask-manager.ts`
|
||||
|
||||
验收标准:
|
||||
|
||||
- `map.ol.ts` 文件长度和职责明显收缩;
|
||||
- 点图层、Popup、基地裁切三类逻辑各自独立;
|
||||
- 现有地图交互行为不变。
|
||||
|
||||
---
|
||||
|
||||
## 8. 阶段六:组件瘦身
|
||||
|
||||
## 8.1 `GisView.vue`
|
||||
|
||||
- [x] 仅保留地图容器、地图初始化调用、组件挂载
|
||||
- [x] 移除配置请求和复杂 watch 编排逻辑
|
||||
- [x] 只通过编排器触发初始化和页面切换
|
||||
|
||||
## 8.2 `LayerController.vue`
|
||||
|
||||
- [x] 只保留树渲染与勾选事件
|
||||
- [x] 移除互斥规则
|
||||
- [x] 移除基础图层初始化编排逻辑
|
||||
|
||||
## 8.3 `MapLegend.vue`
|
||||
|
||||
- [x] 只保留图例渲染与点击事件分发
|
||||
- [x] 不直接调用地图实例
|
||||
|
||||
## 8.4 `MapFilter.vue`
|
||||
|
||||
- [x] 只保留表单与用户输入
|
||||
- [x] 搜索、容量、时间、基地变化全部通过编排器分发
|
||||
- [x] 不直接修改图例运行态和锚点显隐
|
||||
|
||||
验收标准:
|
||||
|
||||
- 组件文件职责单一;
|
||||
- UI 组件中不再出现大段业务逻辑;
|
||||
- 地图相关行为主要集中在编排层和 Store。
|
||||
|
||||
---
|
||||
|
||||
## 9. 阶段七:性能优化
|
||||
|
||||
## 9.1 请求与缓存优化
|
||||
|
||||
- [x] 将 `GisUrlList.ts` 预编译为索引字典,而不是每次请求时重建
|
||||
- [x] 实现真实请求去重
|
||||
- [x] 增加请求取消能力,避免菜单切换时旧请求回写
|
||||
- [x] 对图层加载增加并发控制
|
||||
- [x] 将缓存 key 与图层 key、筛选条件绑定
|
||||
|
||||
## 9.2 锚点显示优化
|
||||
|
||||
- [x] 图例切换时只处理目标图例对应的锚点集合
|
||||
- [x] 图层切换时优先切换图层可见性,不重复加点
|
||||
- [x] 减少 hover 时全量点图层重绘
|
||||
- [x] 减少样式函数中的业务判断复杂度
|
||||
|
||||
验收标准:
|
||||
|
||||
- 首屏加载时长不高于当前;
|
||||
- 图层勾选、图例勾选、基地切换响应速度优于当前;
|
||||
- 菜单快速切换时不出现旧数据回写。
|
||||
|
||||
---
|
||||
|
||||
## 10. 回归测试清单
|
||||
|
||||
每完成一个阶段,至少回归以下功能:
|
||||
|
||||
- [x] 地图初始化正常
|
||||
- [x] 默认基础图层正常显示
|
||||
- [x] 图层树勾选与取消勾选正常
|
||||
- [x] 图例随图层选中动态显示
|
||||
- [x] 图例点击能正确控制锚点显隐
|
||||
- [x] 基地切换后区域裁切和锚点过滤正常
|
||||
- [x] 锚点 hover Popup 正常
|
||||
- [x] 锚点点击详情弹窗正常
|
||||
- [x] 时间筛选、容量筛选、搜索定位正常
|
||||
- [x] 视频监控站与 AI 视频监控站互斥正常
|
||||
- [x] 菜单切换后地图数据不串页
|
||||
|
||||
---
|
||||
|
||||
## 11. 实施顺序建议
|
||||
|
||||
推荐严格按以下顺序执行:
|
||||
|
||||
1. 阶段一:现状收口与问题修复
|
||||
2. 阶段二:规则收口
|
||||
3. 阶段三:拆分 Store
|
||||
4. 阶段四:建立统一编排层
|
||||
5. 阶段五:拆分 OpenLayers 渲染层
|
||||
6. 阶段六:组件瘦身
|
||||
7. 阶段七:性能优化
|
||||
|
||||
不建议直接跳到渲染层拆分或性能优化,否则会在旧结构上重复返工。
|
||||
|
||||
---
|
||||
|
||||
## 12. 本轮交付标准
|
||||
|
||||
当本清单全部完成后,应达到以下结果:
|
||||
|
||||
- 地图模块核心职责划分清晰;
|
||||
- 图层树、图例、锚点、筛选、基地切换链路可追踪;
|
||||
- 关键规则不再散落在多个组件里;
|
||||
- `map.ts` 和 `map.ol.ts` 体积明显下降;
|
||||
- 新增地图业务时有明确扩展点;
|
||||
- 后续继续做底图体系优化、长期性能建设时不需要再推翻本轮结构。
|
||||
15
frontend-sjgl/index.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/logo.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="qgc-buji-web" />
|
||||
<meta name="keywords" content="qgc-buji-web" />
|
||||
<title>全过程数据管理子系统</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
97
frontend-sjgl/package.json
Normal file
@ -0,0 +1,97 @@
|
||||
{
|
||||
"name": "qgc-buji-web",
|
||||
"version": "1.2.0",
|
||||
"scripts": {
|
||||
"dev": "vite serve --mode development",
|
||||
"build": "vite build --mode production",
|
||||
"build:mvn": "vite build --mode production",
|
||||
"serve": "vite preview",
|
||||
"lint": "eslint src/**/*.{ts,js,vue} --fix",
|
||||
"prettier": "prettier --write ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons-vue": "^7.0.1",
|
||||
"@element-plus/icons-vue": "^2.0.10",
|
||||
"@turf/turf": "^7.3.5",
|
||||
"@types/js-cookie": "^3.0.2",
|
||||
"@univerjs-pro/exchange-client": "0.15.0",
|
||||
"@univerjs/core": "0.14.0",
|
||||
"@univerjs/preset-sheets-core": "^0.14.0",
|
||||
"@univerjs/presets": "^0.14.0",
|
||||
"@vueuse/core": "^9.1.1",
|
||||
"@wangeditor/editor": "^5.0.0",
|
||||
"@wangeditor/editor-for-vue": "^5.1.10",
|
||||
"ant-design-vue": "latest",
|
||||
"antdv-draggable-modal": "^1.1.6",
|
||||
"axios": "^1.2.0",
|
||||
"better-scroll": "^2.4.2",
|
||||
"cesium": "^1.141.0",
|
||||
"dayjs": "^1.11.20",
|
||||
"default-passive-events": "^2.0.0",
|
||||
"dom-to-image": "^2.6.0",
|
||||
"echarts": "^5.2.2",
|
||||
"element-plus": "^2.2.27",
|
||||
"esri-leaflet": "^3.0.19",
|
||||
"exceljs": "^4.4.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"js-base64": "^3.7.5",
|
||||
"js-cookie": "^3.0.1",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"jszip": "^3.10.1",
|
||||
"leaflet": "^1.9.4",
|
||||
"lodash": "^4.18.1",
|
||||
"moment": "^2.30.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"ol": "^10.8.0",
|
||||
"path-browserify": "^1.0.1",
|
||||
"path-to-regexp": "^6.2.0",
|
||||
"pdfjs-dist": "^6.0.227",
|
||||
"pinia": "^2.0.12",
|
||||
"react": "18",
|
||||
"react-dom": "18",
|
||||
"screenfull": "^6.0.0",
|
||||
"sortablejs": "^1.14.0",
|
||||
"video.js": "^8.23.7",
|
||||
"videojs-contrib-hls": "^5.15.0",
|
||||
"vue": "^3.2.40",
|
||||
"vue-ant-modal-enhance": "^1.2.2",
|
||||
"vue-i18n": "^9.1.9",
|
||||
"vue-router": "^4.1.6",
|
||||
"vuedraggable": "^2.24.3",
|
||||
"wujie": "^1.0.24",
|
||||
"wujie-vue3": "^1.0.24",
|
||||
"xlsx": "^0.18.5",
|
||||
"xlsx-js-style": "^1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^16.2.3",
|
||||
"@commitlint/config-conventional": "^16.2.1",
|
||||
"@types/dom-to-image": "^2.6.7",
|
||||
"@types/lodash": "^4.17.24",
|
||||
"@types/node": "^16.11.7",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
"@types/path-browserify": "^1.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.19.0",
|
||||
"@typescript-eslint/parser": "^5.19.0",
|
||||
"@vitejs/plugin-vue": "^4.0.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"eslint": "^8.14.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-vue": "^8.6.0",
|
||||
"fast-glob": "^3.2.11",
|
||||
"husky": "^7.0.4",
|
||||
"postcss": "^8.4.20",
|
||||
"prettier": "^2.6.2",
|
||||
"sass": "^1.53.0",
|
||||
"tailwindcss": "^3.2.4",
|
||||
"typescript": "latest",
|
||||
"vite": "^4.0.3",
|
||||
"vite-plugin-cesium": "^1.2.22",
|
||||
"vite-plugin-svg-icons": "^2.0.1",
|
||||
"vue-tsc": "latest"
|
||||
},
|
||||
"repository": "https://gitee.com/youlaiorg/vue3-element-admin.git",
|
||||
"author": "有来开源组织",
|
||||
"license": "MIT"
|
||||
}
|
||||
13865
frontend-sjgl/pnpm-lock.yaml
Normal file
6
frontend-sjgl/postcss.config.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
BIN
frontend-sjgl/public/file/注册操作手册.docx
Normal file
BIN
frontend-sjgl/public/file/过鱼设施数据填报操作手册.docx
Normal file
BIN
frontend-sjgl/public/file/鱼种类字典数据.xlsx
Normal file
BIN
frontend-sjgl/public/logo.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
1
frontend-sjgl/readme.md
Normal file
@ -0,0 +1 @@
|
||||
这里放置前端项目的readme文件
|
||||
19
frontend-sjgl/src/App.vue
Normal file
@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { ElConfigProvider } from 'element-plus';
|
||||
import { useAppStore, usetTheme } from '@/store/modules/app';
|
||||
import locale from 'ant-design-vue/es/locale/zh_CN';
|
||||
|
||||
const appStore = useAppStore();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!--
|
||||
1.地图抽吸
|
||||
2.地图文字和点显示
|
||||
-->
|
||||
<el-config-provider :locale="appStore.locale" :size="appStore.size">
|
||||
<a-config-provider :theme="usetTheme" :locale="locale">
|
||||
<router-view />
|
||||
</a-config-provider>
|
||||
</el-config-provider>
|
||||
</template>
|
||||
310
frontend-sjgl/src/api/DataQueryMenuModule/index.ts
Normal file
@ -0,0 +1,310 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 基础信息 集团/公司
|
||||
export function getCompanyList(data) {
|
||||
return request({
|
||||
url: '/env/hycd/selectForDropdown',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
// 基础信息 表格
|
||||
export function getPowerTableList(data) {
|
||||
return request({
|
||||
url: '/env/engInfo/vmsstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 基础信息 编辑
|
||||
export function updatePowerInfo(data) {
|
||||
return request({
|
||||
url: '/env/engInfo/update',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 基础信息 删除
|
||||
export function deletePowerInfo(data) {
|
||||
return request({
|
||||
url: '/env/engInfo/delete',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 鱼类基础信息 科
|
||||
export function getFishResourceList(data) {
|
||||
return request({
|
||||
url: '/fpr/fishDic/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 鱼类基础信息 表格
|
||||
export function getFishResourceZYList(data) {
|
||||
return request({
|
||||
url: '/fpr/fishDic/zy/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 批复文件
|
||||
export function getApprovalStatusList(data) {
|
||||
return request({
|
||||
url: '/eng/base/eiaapproval/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 生态流量运行数据 - 小时
|
||||
|
||||
export function getFlowDataList(data) {
|
||||
return request({
|
||||
url: '/eq/data/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 生态流量运行数据 - 日
|
||||
|
||||
export function getFlowDataDayList(data) {
|
||||
return request({
|
||||
url: '/eq/data/day/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 生态流量运行数据 - 月
|
||||
|
||||
export function getFlowDataMonthList(data) {
|
||||
return request({
|
||||
url: '/eq/data/drtp/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 水质监测数据 - 断面
|
||||
export function getWaterDataSectionList(data) {
|
||||
return request({
|
||||
url: '/wq/msstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 水质监测数据 - 小时
|
||||
export function getWaterDataList(data) {
|
||||
return request({
|
||||
url: '/wq/data/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 水质监测数据 - 日
|
||||
export function getWaterDataDayList(data) {
|
||||
return request({
|
||||
url: '/wq/data/day/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 水质监测数据 - 月
|
||||
export function getWaterDataMonthList(data) {
|
||||
return request({
|
||||
url: '/wq/data/drtp/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 水质监测数据 编辑
|
||||
export function updateWaterDataInfo(data) {
|
||||
return request({
|
||||
url: '/wq/updateWqRsData',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 水质监测数据 删除
|
||||
export function deleteWaterDataInfo(data) {
|
||||
return request({
|
||||
url: '/wq/removeKendoByIds',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 垂向 - 列表
|
||||
export function getVerticalList(data) {
|
||||
return request({
|
||||
url: '/wt/cxDetail/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 垂向 - 编辑
|
||||
export function updateVerticalInfo(data) {
|
||||
return request({
|
||||
url: '/wt/cxDetail/updateWtvtRData',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 垂向 - 删除
|
||||
export function deleteVerticalInfo(data) {
|
||||
return request({
|
||||
url: '/wt/cxDetail/removeKendoByIds',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 表层水温 - 断面
|
||||
export function getSurfaceTempSectionList(data) {
|
||||
return request({
|
||||
url: '/wt/msstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 表层水温 - 小时
|
||||
export function getSurfaceTempList(data) {
|
||||
return request({
|
||||
url: '/wt/alongDetail/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 表层水温 - 日
|
||||
export function getSurfaceTempDayList(data) {
|
||||
return request({
|
||||
url: '/wt/alongDetail/day/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 表层水温 - 月
|
||||
export function getSurfaceTempMonthList(data) {
|
||||
return request({
|
||||
url: '/wt/alongDetail/drtp/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 表层水温 - 编辑
|
||||
export function updateSurfaceTempInfo(data) {
|
||||
return request({
|
||||
url: '/wt/alongDetail/updateWtrvRData',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 表层水温 - 删除
|
||||
export function deleteSurfaceTempInfo(data) {
|
||||
return request({
|
||||
url: '/wt/alongDetail/drtp/removeKendoByIds',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 表层水温 - 数据分析 - 断面
|
||||
export function getSurfaceTempAnalysisList(data) {
|
||||
return request({
|
||||
url: '/wt/msstbprpt/eng/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 表层水温 - 数据分析 - excel
|
||||
export function getSurfaceTempAnalysisExcel(data) {
|
||||
return request({
|
||||
url: '/wt/wtrvAmend/dayAmend/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 表层水温 - 数据分析 - 保存
|
||||
export function saveSurfaceTempAnalysisExcel(data) {
|
||||
return request({
|
||||
url: '/wt/wtrvAmend/dayAmend/saveAmendData',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 过鱼设施名称 - 断面
|
||||
export function getFishReleaseMonitorSectionList(data) {
|
||||
return request({
|
||||
url: '/fp/msstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 过鱼监测数据
|
||||
export function getFishReleaseMonitorList(data) {
|
||||
return request({
|
||||
url: '/fp/query/qgc/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 鱼类 放鱼
|
||||
export function getFishReleaseList(data) {
|
||||
return request({
|
||||
url: '/fb/fishrun/qgc/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 流量站 - 断面
|
||||
export function getFlowStationSectionList(data) {
|
||||
return request({
|
||||
url: '/zq/msstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 流量站 - 小时
|
||||
export function getFlowStationList(data) {
|
||||
return request({
|
||||
url: '/zq/river/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 流量站 - 日
|
||||
export function getFlowStationDayList(data) {
|
||||
return request({
|
||||
url: '/zq/river/day/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 流量站 - 月
|
||||
export function getFlowStationMonthList(data) {
|
||||
return request({
|
||||
url: '/zq/river/drtp/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 流量站 - 编辑
|
||||
export function updateFlowStationInfo(data) {
|
||||
return request({
|
||||
url: '/zq/river/updateRiverRData',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 流量站 - 删除
|
||||
export function deleteFlowStationInfo(data) {
|
||||
return request({
|
||||
url: '/zq/river/removeKendoByIds',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
175
frontend-sjgl/src/api/auth/index.ts
Normal file
@ -0,0 +1,175 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { LoginData, TokenResult, VerifyCode } from './types';
|
||||
export function getAccessToken() {
|
||||
return request({
|
||||
url: '/register/accessToken',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param data {LoginForm}
|
||||
* @returns
|
||||
*/
|
||||
export function loginApi(data: LoginData): AxiosPromise<TokenResult> {
|
||||
return request({
|
||||
url: '/user/login',
|
||||
method: 'post',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 注销
|
||||
*/
|
||||
export function logoutApi() {
|
||||
return request({
|
||||
url: '/user/logout',
|
||||
method: 'post'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图片验证码
|
||||
*/
|
||||
export function getCaptcha(): AxiosPromise<VerifyCode> {
|
||||
return request({
|
||||
url: '/user/code?t=' + new Date().getTime().toString(),
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户注册
|
||||
*/
|
||||
export function registerUser(data: any): AxiosPromise<any> {
|
||||
return request({
|
||||
url: '/sms/register',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取流域列表
|
||||
* @param companyId 公司ID(可选),如果传入则根据公司获取流域列表
|
||||
*/
|
||||
export function getBasinList(): AxiosPromise<any[]> {
|
||||
return request({
|
||||
url: '/register/dropdown/rvcd',
|
||||
method: 'get',
|
||||
headers: {
|
||||
'register-token': localStorage.getItem('register-token') || ''
|
||||
}
|
||||
// params: baseid ? { baseid } : {}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取集团列表(无参数,获取全量集团)
|
||||
*/
|
||||
export function getGroupList(): AxiosPromise<any[]> {
|
||||
return request({
|
||||
url: '/register/dropdown/hycd',
|
||||
method: 'get',
|
||||
params: { lx: 1 },
|
||||
headers: {
|
||||
'register-token': localStorage.getItem('register-token') || ''
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据集团获取公司列表
|
||||
*/
|
||||
export function getCompanyList(): AxiosPromise<any[]> {
|
||||
return request({
|
||||
url: '/register/dropdown/hycd',
|
||||
method: 'get',
|
||||
params: { lx: 2 },
|
||||
headers: {
|
||||
'register-token': localStorage.getItem('register-token') || ''
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据流域获取电站列表
|
||||
*/
|
||||
export function getStationList(params: any): AxiosPromise<any[]> {
|
||||
return request({
|
||||
url: '/register/dropdown/engInfo',
|
||||
method: 'post',
|
||||
data: params,
|
||||
headers: {
|
||||
'register-token': localStorage.getItem('register-token') || ''
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送短信验证码
|
||||
* @param phone 手机号
|
||||
* @param type 验证码类型:1-注册 2-找回密码
|
||||
*/
|
||||
export function sendSmsCode(phone: string, type = 1): AxiosPromise<any> {
|
||||
return request({
|
||||
url: '/sms/sendCode',
|
||||
method: 'post',
|
||||
data: { phone, type }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证短信验证码
|
||||
* @param phone 手机号
|
||||
* @param code 验证码
|
||||
* @param type 验证码类型:1-注册 2-找回密码
|
||||
*/
|
||||
export function verifySmsCode(
|
||||
phone: string,
|
||||
code: string,
|
||||
type = 1
|
||||
): AxiosPromise<any> {
|
||||
return request({
|
||||
url: '/sms/verifyCode',
|
||||
method: 'post',
|
||||
data: { phone, code, type }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 短信验证码登录
|
||||
* @param phone 手机号
|
||||
* @param code 验证码
|
||||
*/
|
||||
export function smsLoginApi(
|
||||
phone: string,
|
||||
code: string
|
||||
): AxiosPromise<TokenResult> {
|
||||
return request({
|
||||
url: '/sms/login',
|
||||
method: 'post',
|
||||
data: { phone, code }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置密码
|
||||
* @param phone 手机号
|
||||
* @param code 验证码
|
||||
* @param password 新密码
|
||||
*/
|
||||
export function resetPassword(
|
||||
phone: string,
|
||||
code: string,
|
||||
password: string
|
||||
): AxiosPromise<any> {
|
||||
return request({
|
||||
url: '/sms/resetPassword',
|
||||
method: 'post',
|
||||
data: { phone, code, password }
|
||||
});
|
||||
}
|
||||
34
frontend-sjgl/src/api/auth/types.ts
Normal file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* 登录数据类型
|
||||
*/
|
||||
export interface LoginData {
|
||||
username: string;
|
||||
password: string;
|
||||
code: string;
|
||||
uuid: string;
|
||||
/**
|
||||
* 验证码Code
|
||||
*/
|
||||
//verifyCode: string;
|
||||
/**
|
||||
* 验证码Code服务端缓存key(UUID)
|
||||
*/
|
||||
// verifyCodeKey: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Token响应类型
|
||||
*/
|
||||
export interface TokenResult {
|
||||
token: string;
|
||||
refreshToken: string;
|
||||
expires: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证码类型
|
||||
*/
|
||||
export interface VerifyCode {
|
||||
verifyCodeImg: string;
|
||||
verifyCodeKey: string;
|
||||
}
|
||||
9
frontend-sjgl/src/api/changePassWord/index.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import request from '@/utils/request';
|
||||
//修改密码
|
||||
export function updatePassword(params:any) {
|
||||
return request({
|
||||
url: '/user/updatePassword',
|
||||
method: 'post',
|
||||
data: params
|
||||
});
|
||||
}
|
||||
139
frontend-sjgl/src/api/dept/index.ts
Normal file
@ -0,0 +1,139 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { DeptForm, DeptQuery, Dept } from './types';
|
||||
|
||||
|
||||
//获取组织架构
|
||||
|
||||
export function getTreelist(queryParams:any) {
|
||||
return request({
|
||||
url: '/system/organization/getOrgTree',
|
||||
method: 'POST',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
//新增企业或部门
|
||||
|
||||
export function addTreelist(queryParams:any) {
|
||||
return request({
|
||||
url: '/system/organization/addOrg',
|
||||
method: 'POST',
|
||||
data: queryParams
|
||||
});
|
||||
}
|
||||
// 修改企业部门
|
||||
|
||||
export function updataTreelist(queryParams:any) {
|
||||
return request({
|
||||
url: '/system/organization/updateById',
|
||||
method: 'POST',
|
||||
data: queryParams
|
||||
});
|
||||
}
|
||||
//删除企业
|
||||
export function delTreelist(queryParams:any) {
|
||||
return request({
|
||||
url: '/system/organization/deleteById',
|
||||
method: 'POST',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
//获取部门信息
|
||||
export function gettableData(queryParams:any) {
|
||||
return request({
|
||||
url: '/system/organization/getOrganizationById',
|
||||
method: 'POST',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
//部门是否有效
|
||||
export function deptIsVaild(queryParams:any) {
|
||||
return request({
|
||||
url: '/system/organization/setIsValid',
|
||||
method: 'POST',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
|
||||
//修改部门信息
|
||||
export function reviseDepartment(queryParams:any) {
|
||||
return request({
|
||||
url: '/system/organization/updateById',
|
||||
method: 'POST',
|
||||
data: queryParams
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 部门树形表格
|
||||
*
|
||||
* @param queryParams
|
||||
*/
|
||||
export function listDepartments(queryParams?: DeptQuery): AxiosPromise<Dept[]> {
|
||||
return request({
|
||||
url: '/api/v1/dept',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 部门下拉列表
|
||||
*/
|
||||
export function listDeptOptions(): AxiosPromise<Dept[]> {
|
||||
return request({
|
||||
url: '/api/v1/dept/options',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取部门详情
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
export function getDeptForm(id: string): AxiosPromise<DeptForm> {
|
||||
return request({
|
||||
url: '/api/v1/dept/' + id + '/form',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增部门
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
export function addDept(data: DeptForm) {
|
||||
return request({
|
||||
url: '/api/v1/dept',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改部门
|
||||
*
|
||||
* @param id
|
||||
* @param data
|
||||
*/
|
||||
export function updateDept(id: string, data: DeptForm) {
|
||||
return request({
|
||||
url: '/api/v1/dept/' + id,
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除部门
|
||||
*
|
||||
* @param ids
|
||||
*/
|
||||
export function deleteDept(ids: string) {
|
||||
return request({
|
||||
url: '/api/v1/dept/' + ids,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
34
frontend-sjgl/src/api/dept/types.ts
Normal file
@ -0,0 +1,34 @@
|
||||
/**
|
||||
* 部门查询参数
|
||||
*/
|
||||
export interface DeptQuery {
|
||||
keywords: string | undefined;
|
||||
status: number | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* 部门类型
|
||||
*/
|
||||
export interface Dept {
|
||||
id: string;
|
||||
name: string;
|
||||
parentId: string;
|
||||
treePath: string;
|
||||
sort: number;
|
||||
status: number;
|
||||
leader?: string;
|
||||
mobile?: string;
|
||||
email?: string;
|
||||
children: Dept[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 部门表单类型
|
||||
*/
|
||||
export interface DeptForm {
|
||||
id?: string;
|
||||
parentId: string;
|
||||
name: string;
|
||||
sort: number;
|
||||
status: number;
|
||||
}
|
||||
250
frontend-sjgl/src/api/dict/index.ts
Normal file
@ -0,0 +1,250 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import {
|
||||
DictQuery,
|
||||
DictPageResult,
|
||||
DictTypeForm,
|
||||
DictItemQuery,
|
||||
DictItemPageResult,
|
||||
DictItemForm
|
||||
} from './types';
|
||||
// 查询字典
|
||||
export function getTreelist(params:any) {
|
||||
return request({
|
||||
url: '/system/dictionary/dictList',
|
||||
method: 'get',
|
||||
params: params
|
||||
});
|
||||
}
|
||||
|
||||
// 新增字典
|
||||
export function addDict(params:any) {
|
||||
return request({
|
||||
url: '/system/dictionary/addDict',
|
||||
method: 'post',
|
||||
data: params
|
||||
});
|
||||
}
|
||||
|
||||
// 修改字典
|
||||
export function updateDict(params:any) {
|
||||
return request({
|
||||
url: '/system/dictionary/updateDict',
|
||||
method: 'post',
|
||||
data: params
|
||||
});
|
||||
}
|
||||
// 删除字典
|
||||
export function deleteById(params:any) {
|
||||
return request({
|
||||
url: '/system/dictionary/deleteById',
|
||||
method: 'post',
|
||||
params: params
|
||||
});
|
||||
}
|
||||
// 字典排序
|
||||
export function changeDictOrder(params:any) {
|
||||
return request({
|
||||
url: '/system/dictionary/changeDictOrder',
|
||||
method: 'post',
|
||||
params: params
|
||||
});
|
||||
}
|
||||
// 查询字典项
|
||||
export function getDictItemById(params:any) {
|
||||
return request({
|
||||
url: '/system/dictionaryItems/page',
|
||||
method: 'get',
|
||||
params: params
|
||||
});
|
||||
}
|
||||
|
||||
// 新增字典项
|
||||
export function addDictionaryItem(params:any) {
|
||||
return request({
|
||||
url: '/system/dictionaryItems/addDictionaryItem',
|
||||
method: 'post',
|
||||
data: params
|
||||
});
|
||||
}
|
||||
|
||||
// 修改字典项
|
||||
export function updateDictionaryItem(params:any) {
|
||||
return request({
|
||||
url: '/system/dictionaryItems/updateDictionaryItem',
|
||||
method: 'post',
|
||||
data: params
|
||||
});
|
||||
}
|
||||
// 删除字典项
|
||||
export function deleteDictItemById(params:any) {
|
||||
return request({
|
||||
url: '/system/dictionaryItems/deleteDictItemById',
|
||||
method: 'post',
|
||||
params: params
|
||||
});
|
||||
}
|
||||
// 批量删除字典项
|
||||
export function deleteDictItemByIds(params:any) {
|
||||
return request({
|
||||
url: '/system/dictionaryItems/deleteDictItemByIds',
|
||||
method: 'post',
|
||||
params: params
|
||||
});
|
||||
}
|
||||
|
||||
// 字典项排序
|
||||
export function changeItemOrder(params:any) {
|
||||
return request({
|
||||
url: '/system/dictionaryItems/changeItemOrder',
|
||||
method: 'post',
|
||||
params: params
|
||||
});
|
||||
}
|
||||
//根据字典编号查询字典项列表
|
||||
export function getDictItemsByCode(params:any) {
|
||||
return request({
|
||||
url: '/system/dictionary/getDictItemsByCode',
|
||||
method: 'get',
|
||||
params: params
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 获取字典类型分页列表
|
||||
*
|
||||
* @param queryParams
|
||||
*/
|
||||
export function listDictTypePages(
|
||||
queryParams: DictQuery
|
||||
): AxiosPromise<DictPageResult> {
|
||||
return request({
|
||||
url: '/api/v1/dict/types/pages',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字典类型表单数据
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
export function getDictTypeForm(id: number): AxiosPromise<DictTypeForm> {
|
||||
return request({
|
||||
url: '/api/v1/dict/types/' + id + '/form',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增字典类型
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
export function addDictType(data: DictTypeForm) {
|
||||
return request({
|
||||
url: '/api/v1/dict/types',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改字典类型
|
||||
*
|
||||
* @param id
|
||||
* @param data
|
||||
*/
|
||||
export function updateDictType(id: number, data: DictTypeForm) {
|
||||
return request({
|
||||
url: '/api/v1/dict/types/' + id,
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除字典类型
|
||||
*/
|
||||
export function deleteDictTypes(ids: string) {
|
||||
return request({
|
||||
url: '/api/v1/dict/types/' + ids,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字典类型的数据项
|
||||
*
|
||||
* @param typeCode 字典类型编码
|
||||
*/
|
||||
export function getDictionaries(typeCode: string): AxiosPromise<any[]> {
|
||||
return request({
|
||||
url: '/api/v1/dict/types/' + typeCode + '/items',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字典项分页列表
|
||||
*/
|
||||
export function listDictItemPages(
|
||||
queryParams: DictItemQuery
|
||||
): AxiosPromise<DictItemPageResult> {
|
||||
return request({
|
||||
url: '/api/v1/dict/items/pages',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字典数据项表单数据
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
export function getDictItemData(id: number): AxiosPromise<DictItemForm> {
|
||||
return request({
|
||||
url: '/api/v1/dict/items/' + id + '/form',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增字典项
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
export function saveDictItem(data: DictItemForm) {
|
||||
return request({
|
||||
url: '/api/v1/dict/items',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改字典项
|
||||
*
|
||||
* @param id
|
||||
* @param data
|
||||
*/
|
||||
export function updateDictItem(id: number, data: DictItemForm) {
|
||||
return request({
|
||||
url: '/api/v1/dict/items/' + id,
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除字典数据项
|
||||
*
|
||||
* @param ids 字典项ID,多个以英文逗号(,)分割
|
||||
*/
|
||||
export function deleteDictItems(ids: string) {
|
||||
return request({
|
||||
url: '/api/v1/dict/items/' + ids,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
92
frontend-sjgl/src/api/dict/types.ts
Normal file
@ -0,0 +1,92 @@
|
||||
/**
|
||||
* 字典查询参数
|
||||
*/
|
||||
export interface DictQuery extends PageQuery {
|
||||
/**
|
||||
* 字典名称
|
||||
*/
|
||||
name?: string;
|
||||
}
|
||||
interface PageResult<T> {
|
||||
total: number;
|
||||
list: T[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 字典类型
|
||||
*/
|
||||
export interface Dict {
|
||||
id: number;
|
||||
code: string;
|
||||
name: string;
|
||||
status: number;
|
||||
remark: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字典分页项类型声明
|
||||
*/
|
||||
export type DictPageResult = PageResult<Dict[]>;
|
||||
|
||||
/**
|
||||
* 字典表单类型声明
|
||||
*/
|
||||
export interface DictTypeForm {
|
||||
id: number | undefined;
|
||||
name: string;
|
||||
code: string;
|
||||
status: number;
|
||||
remark: string;
|
||||
}
|
||||
interface PageQuery {
|
||||
pageIndex: number;
|
||||
pageSize: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字典项查询参数类型声明
|
||||
*/
|
||||
export interface DictItemQuery extends PageQuery {
|
||||
/**
|
||||
* 字典项名称
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* 字典类型编码
|
||||
*/
|
||||
typeCode?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字典数据项类型
|
||||
*/
|
||||
export interface DictItem {
|
||||
id: number;
|
||||
name: string;
|
||||
value: string;
|
||||
typeCode: string;
|
||||
sort: number;
|
||||
status: number;
|
||||
defaulted: number;
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字典分页项类型声明
|
||||
*/
|
||||
export type DictItemPageResult = PageResult<DictItem[]>;
|
||||
|
||||
/**
|
||||
* 字典表单类型声明
|
||||
*/
|
||||
export interface DictItemForm {
|
||||
id?: number;
|
||||
typeCode?: string;
|
||||
typeName?: string;
|
||||
name: string;
|
||||
code: string;
|
||||
value: string;
|
||||
status: number;
|
||||
sort: number;
|
||||
remark: string;
|
||||
}
|
||||
138
frontend-sjgl/src/api/guoYuSheShiShuJuTianBao/index.ts
Normal file
@ -0,0 +1,138 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 分页查询过鱼数据
|
||||
export function getFishDraftPage(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/page',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//新增过鱼数据
|
||||
export function addFishDraft(queryParams: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/saveDraft',
|
||||
method: 'post',
|
||||
data: queryParams
|
||||
});
|
||||
}
|
||||
//修改过鱼数据
|
||||
export function editFishDraft(queryParams: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/updateDraft',
|
||||
method: 'post',
|
||||
data: queryParams
|
||||
});
|
||||
}
|
||||
//删除 过鱼数据
|
||||
export function delFishDraft(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/batchRemoveDraft',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//提交过鱼数据
|
||||
export function submitFishDraft(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/submitDrafts',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//提交全部过鱼数据
|
||||
export function batchApproveAll() {
|
||||
return request({
|
||||
url: '/data/fishDraft/submitDraftsAll',
|
||||
method: 'post'
|
||||
});
|
||||
}
|
||||
//审批过鱼数据
|
||||
export function successFishDraft(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/batchApprove',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//驳回过鱼数据
|
||||
export function rejectFishDraft(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/reject',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 导入zip
|
||||
export function importFishZip(data: FormData) {
|
||||
return request({
|
||||
url: '/data/fishDraft/importZip',
|
||||
method: 'post',
|
||||
data,
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
timeout: 1000 * 60 * 5 // 5分钟
|
||||
});
|
||||
}
|
||||
// 取消导入任务
|
||||
export function cancelImportTask(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/cancelImport',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//检测用户导入状态
|
||||
export function checkImportStatus() {
|
||||
return request({
|
||||
url: '/data/fishDraft/checkImportStatus',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
// 查询用户导入结果
|
||||
export function getLastImportResult() {
|
||||
return request({
|
||||
url: '/data/fishDraft/getLastImportResult',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
export function deleteFile(params: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/deleteFile',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
// 批量保存草稿
|
||||
export function batchSaveDraft(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/batchSaveDraft',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 批量删除 审批已驳回的
|
||||
export function batchRemoveDraft(data: any) {
|
||||
return request({
|
||||
url: '/data/approvalMain/batchDelete',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 过鱼倒数统计
|
||||
export function statistics(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/statistics',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 催促
|
||||
export function batchUrgeContent(data: any) {
|
||||
return request({
|
||||
url: '/sms/batchUrgeContent',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
61
frontend-sjgl/src/api/map.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 获取图例列表
|
||||
export function getModuleMapLegendList(params?: { moduleId?: string }) {
|
||||
const url = params?.moduleId
|
||||
? `/mapLegend/getModuleMapLegendList?moduleId=${params.moduleId}`
|
||||
: '/mapLegend/getModuleMapLegendList';
|
||||
return request({
|
||||
url,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
// 获取地图配置列表
|
||||
export function getMapList(data: any) {
|
||||
return request({
|
||||
url: '/mapmodule/getMapData',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 获取梯级流域地图
|
||||
export function getQgcRvcd(data: any) {
|
||||
return request({
|
||||
url: '/eng/base/rsvrcscdb/getQgcRvcd',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 获取梯级流域下拉框列表
|
||||
export function getRvcdList(data: any) {
|
||||
return request({
|
||||
url: '/eng/base/rsvrcscdb/rvcd',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 获取梯级流域下拉框图表数据
|
||||
export function getKendoList(data: any) {
|
||||
return request({
|
||||
url: '/eng/base/rsvrcscdb/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 鱼类分布查询 - 站点查询
|
||||
export function getFishPointList(data: any) {
|
||||
return request({
|
||||
url: '/wte/we/fishPoint/qgc/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 鱼类分布查询 -鱼查询
|
||||
export function getFishList(data: any) {
|
||||
return request({
|
||||
url: '/wte/we/fishList/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
544
frontend-sjgl/src/api/mapModal/index.ts
Normal file
@ -0,0 +1,544 @@
|
||||
import request from '@/utils/request';
|
||||
export function getStcdDetail(url: string, stcd: string) {
|
||||
return request({
|
||||
url: url,
|
||||
method: 'get',
|
||||
params: { stcd }
|
||||
});
|
||||
}
|
||||
// 公共接口 - post
|
||||
export function queryPostUrlList(url: string, data: any) {
|
||||
return request({
|
||||
url: url,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 公共接口 - 获取预览地址
|
||||
export function getIdUrl(params: any) {
|
||||
return request({
|
||||
url: import.meta.env.VITE_APP_ATTACHMENT_URL + '/get',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
export function postIdUrl(data: any) {
|
||||
return request({
|
||||
url: import.meta.env.VITE_APP_ATTACHMENT_URL + '/get',
|
||||
method: 'post',
|
||||
data,
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
|
||||
}
|
||||
});
|
||||
}
|
||||
// 查询站点建设状态
|
||||
export function getBuildState(data: any) {
|
||||
return request({
|
||||
url: '/wt/vmsstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data: {
|
||||
filter: data.filter,
|
||||
select: ['bldsttCcode', 'engIwtCode', 'engDwtCode']
|
||||
}
|
||||
});
|
||||
}
|
||||
// 查询鱼类栖息地监测数据类型可用性
|
||||
export function getFishTab(stcd: string) {
|
||||
return request({
|
||||
url: `/wte/we/wer/getWeDefaultData`,
|
||||
method: 'get',
|
||||
params: { stcd }
|
||||
});
|
||||
}
|
||||
// 检查水质站是否启用 AI 预测功能
|
||||
export function checkAnalysisShow(data: any) {
|
||||
return request({
|
||||
url: '/overview/vmsstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 查询站点的关联子站点 (垂向水温、AI 识别)
|
||||
export function getStInfoByStcd(params: any) {
|
||||
return request({
|
||||
url: '/eng/base/msstbprpt/getStInfoByStcd',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
// 检查电站是否有专题配置数据
|
||||
export function checkPowerStationTopic(data: any) {
|
||||
return request({
|
||||
url: '/api/wmp-sys-server/sys/psbmodulelbb/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 全景影像
|
||||
export function getPanoramaList(data: any) {
|
||||
return request({
|
||||
url: '/eq/msstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 实时视频
|
||||
export function getVideoList(data: any) {
|
||||
return request({
|
||||
url: '/vd/msstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 录像视频 - 时间查询
|
||||
export function getNoLiveVideoYear(data: any) {
|
||||
return request({
|
||||
url: '/vd/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 录像视频
|
||||
export function getNoLiveVideoList(data: any) {
|
||||
return request({
|
||||
url: '/vd/runData/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 实时视频单个查询
|
||||
export function getVideoDetail(data: any) {
|
||||
return request({
|
||||
url: '/vd/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 实时视频 回放
|
||||
export function getVideoPlayDetail(data: any) {
|
||||
return request({
|
||||
url: '/vd/runData/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 监测数据 - 电站
|
||||
export function getMonitorData(data: any) {
|
||||
return request({
|
||||
url: '/eq/data/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 监测数据 水温查询 栖息地
|
||||
|
||||
export function getMonitorDataWt(data: any) {
|
||||
return request({
|
||||
url: '/wt/msstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
export function getMonitorDataWq(data: any) {
|
||||
return request({
|
||||
url: '/wq/msstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
export function getMonitorDataZq(data: any) {
|
||||
return request({
|
||||
url: '/zq/msstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 监测数据 - 水温
|
||||
export function getMonitorDataWaterTemp(data: any) {
|
||||
return request({
|
||||
url: '/wt/alongDetail/qgc/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 监测数据 - 水温 - 查询显示 综合/等温
|
||||
export function getMonitorDataWaterTempPowerStation(params: any) {
|
||||
return request({
|
||||
url: '/wt/wtrv/getIoWtrvFlag',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
// 监测数据 - 水温 - 、综合分析导出数据
|
||||
export function exportMonitorDataWaterTempPowerStation(params: any) {
|
||||
return request({
|
||||
url: '/wt/alongDetail/qgc/GetKendoListCust',
|
||||
method: 'post',
|
||||
params,
|
||||
responseType: 'blob'
|
||||
});
|
||||
}
|
||||
|
||||
// 监测数据 - 水温 - 查询是否显示 等温水深
|
||||
export function getMonitorDataWaterTempPowerStation2(params: any) {
|
||||
return request({
|
||||
url: '/wt/alongDetail/qgc/stcdCheck2',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
// 监测数据 - 垂向水温
|
||||
export function getMonitorDataWaterTempVertical(data: any) {
|
||||
return request({
|
||||
url: '/wt/cxDetail/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 监测数据 - 水质 判断是否显示综合分析
|
||||
export function getMonitorDataWaterQuality(data: any) {
|
||||
return request({
|
||||
url: '/wq/vmsstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 监测数据 - 水质 - 获取水质参数
|
||||
export function getMonitorDataWaterQualityDetail(data: any) {
|
||||
return request({
|
||||
url: '/wq/stbprp/GetStbprpYsByStcd',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
// 监测数据 - 水质 - 获取水质数据
|
||||
export function getMonitorDataWaterQualityList(data: any) {
|
||||
return request({
|
||||
url: '/wq/data/noAuth/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 生态流量 - 限制范围查询 - 日
|
||||
export function getMonitorDataWaterTempVerticalDay(data: any) {
|
||||
return request({
|
||||
url: '/eq/interval/qgc/day/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 生态流量 - 限制范围查询 - 小时
|
||||
export function getMonitorDataWaterTempVerticalHour(data: any) {
|
||||
return request({
|
||||
url: '/eq/interval/qgc/hour/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 生态流量 - 查询限制和来源
|
||||
export function getEngLimit(data: any) {
|
||||
return request({
|
||||
url: '/eq/data/getEngLimit',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 生态流量 - 列表 - 日
|
||||
export function getMonitorDataWaterTempVerticalDayList(data: any) {
|
||||
return request({
|
||||
url: '/eq/data/day/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 生态流量 - 列表 - 小时
|
||||
export function getMonitorDataWaterTempVerticalHourList(data: any) {
|
||||
return request({
|
||||
url: '/eq/data/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 在线监测数据
|
||||
export function getMonitorDataOnline(data: any) {
|
||||
return request({
|
||||
url: '/fp/fpssTable/qgc/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 没接
|
||||
export function getMonitorDataFpq(data: any) {
|
||||
return request({
|
||||
url: '/fp/msstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 运行状态
|
||||
export function getRunState(data: any) {
|
||||
return request({
|
||||
url: '/fp/query/qgc/sdfpssr/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
export function getRunStateSecondPlan(data: any) {
|
||||
return request({
|
||||
url: '/fp/run/secondPlan/qgc/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 综合分析
|
||||
|
||||
export function getFishZHFX(data: any) {
|
||||
return request({
|
||||
url: 'fp/run/fish/select',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
export function getRunStateAnalysis(data: any) {
|
||||
return request({
|
||||
url: '/fp/run/analysis/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// ai运行识别
|
||||
export function getAIYXSB(data: any) {
|
||||
return request({
|
||||
url: '/fp/msstbprpt/getStInfoByStcd',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
// ai运行识别 视频/表格
|
||||
export function getAIComList(data: any) {
|
||||
return request({
|
||||
url: '/warn/ai/com/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// ai运行识别 日历
|
||||
export function getAIComCalendar(data: any) {
|
||||
return request({
|
||||
url: '/warn/ai/com/qgc/aiRecord/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// ai运行 日历点击
|
||||
export function getAIComCalendarClick(data: any) {
|
||||
return request({
|
||||
url: '/warn/ai/com/qgc/aiFile/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 鱼类增殖站 - 运行数据 -获取年
|
||||
export function getFishProgressionYear(data: any) {
|
||||
return request({
|
||||
url: '/fb/fbrdmr/getFbRelatedYrByStcd',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
//鱼类增殖站 - 运行数据 -获取鱼
|
||||
export function getFishProgressionFish(data: any) {
|
||||
return request({
|
||||
url: '/fp/fishDic/stcd/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 过程图 - 亲鱼
|
||||
export function getProcessDiagramParentFish(data: any) {
|
||||
return request({
|
||||
url: '/fb/bsmfr/fish/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 过程图 - 产卵/孵化
|
||||
export function getProcessDiagramHatch(data: any, type: 1 | 2) {
|
||||
return request({
|
||||
url: `/fb/fishhatchrecr/fish/GetKendoListCust?type=${type}`,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 过程图 - 鱼苗
|
||||
export function getProcessDiagramFishFry(data: any) {
|
||||
return request({
|
||||
url: '/fb/fishbreedr/fish/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//增值放流情况 获取年
|
||||
export function getNormalAddedSituationYear(data: any) {
|
||||
return request({
|
||||
url: '/fb/msfbrdm/fbFlData/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//增值放流情况 列表
|
||||
export function getNormalAddedSituation(data: any) {
|
||||
return request({
|
||||
url: '/fb/msfbrdm/qgc/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 科研情况
|
||||
export function getNormalResearchSituation(data: any) {
|
||||
return request({
|
||||
url: '/fb/base/researchb/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 珍稀植物园 - 运行数据 没接
|
||||
export function getNormalDataMonitoring2Year(data: any) {
|
||||
return request({
|
||||
url: '/vap/vpr/year/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 珍稀植物园 - 运行数据 列表
|
||||
export function getNormalDataMonitoring2List(data: any) {
|
||||
return request({
|
||||
url: '/vap/vpr/basinVpIntDetail',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 珍稀动物园 - 监测数据 时间
|
||||
export function getNormal2Year(data: any) {
|
||||
return request({
|
||||
url: '/vap/var/year/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 珍稀动物园 - 监测数据 列表 没接
|
||||
export function getNormal2List(data: any) {
|
||||
return request({
|
||||
url: '/vap/var/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 水生生态调查断面 - 监测数据 年份 没接
|
||||
export function getEcologyYear(data: any) {
|
||||
return request({
|
||||
url: '/wte/we/wer/getWeYr',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
// 水生生态调查断面 - 监测数据 调查批次
|
||||
export function getEcologyBatch(data: any) {
|
||||
return request({
|
||||
url: '/wte/we/fisht/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 水生生态调查断面 - 监测数据 调查鱼类列表
|
||||
export function getEcologyList(data: any) {
|
||||
return request({
|
||||
url: '/wte/we/fisht/qgc/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 水生生态调查断面 - 监测数据 水温列表 没接
|
||||
export function getEcologyList1(data: any) {
|
||||
return request({
|
||||
url: '/wte/we/wewtr/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 水生生态调查断面 - 监测数据 水质列表 没接
|
||||
export function getEcologyList2(data: any) {
|
||||
return request({
|
||||
url: '/wte/we/wewqr/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 水生生态调查断面 - 监测数据 流速列表 没接
|
||||
export function getEcologyList3(data: any) {
|
||||
return request({
|
||||
url: '/wte/we/fvR/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 野生动物检测 -现场录像 - 年份
|
||||
export function getLiveFootageYear(data: any) {
|
||||
return request({
|
||||
url: '/wte/wva/default/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 野生动物检测 -现场录像
|
||||
export function getLiveFootageList(data: any) {
|
||||
return request({
|
||||
url: '/wte/wva/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 鱼类分布明细 - 年 没接
|
||||
export function getFishDistributionYear(data: any) {
|
||||
return request({
|
||||
url: '/wte/we/wer/getWeYr',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
// 鱼类分布明细 - 列表
|
||||
export function getFishDistributionList(data: any) {
|
||||
return request({
|
||||
url: '/wte/we/fisht/qgc/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 生态流量泄放设施 - 监测数据 年份 没接
|
||||
export function getFlowDischargeYear(data: any) {
|
||||
return request({
|
||||
url: '/eq/operat/default/year',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
export function getFlowDischargeList(code: string, data: any) {
|
||||
return request({
|
||||
url: `/env/engInfo/stbprpData/GetKendoListCust?tbCode=${code}`,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
159
frontend-sjgl/src/api/menu/index.ts
Normal file
@ -0,0 +1,159 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { MenuQuery, Menu, Resource, MenuForm } from './types';
|
||||
|
||||
//获取菜单表格
|
||||
export function getdata(queryParams:any) {
|
||||
return request({
|
||||
url: '/system/menu/getMenuButtonTree',
|
||||
method: 'post',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
//新增目录
|
||||
export function addmenu(queryParams:any) {
|
||||
return request({
|
||||
url: '/system/menu/addMenu',
|
||||
method: 'post',
|
||||
data: queryParams
|
||||
});
|
||||
}
|
||||
//修改目录
|
||||
export function editmenu(queryParams:any) {
|
||||
return request({
|
||||
url: '/system/menu/updateById',
|
||||
method: 'post',
|
||||
data: queryParams
|
||||
});
|
||||
}
|
||||
//删除
|
||||
export function deltmenu(queryParams:any) {
|
||||
return request({
|
||||
url: '/system/menu/deleteById',
|
||||
method: 'post',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
//排序
|
||||
export function moveOrderno(params:any) {
|
||||
return request({
|
||||
url: '/system/menu/changeMenuOrder',
|
||||
method: 'post',
|
||||
params: params
|
||||
});
|
||||
}
|
||||
//上传图标之前获取ID
|
||||
|
||||
//上传单个图标
|
||||
export function uploadIcon (data:any) {
|
||||
return request({
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
},
|
||||
url: '/system/menu/uploadIcon',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
}
|
||||
//删除单个图标
|
||||
export function moveIcon(params:any) {
|
||||
return request({
|
||||
url: '/system/menu/deleteIcon',
|
||||
method: 'post',
|
||||
params: params
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取路由列表
|
||||
*/
|
||||
export function listRoutes() {
|
||||
return request({
|
||||
url: 'system/menu/treeRoutes',
|
||||
method: 'get',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单表格列表
|
||||
*
|
||||
* @param queryParams
|
||||
*/
|
||||
export function listMenus(queryParams: MenuQuery): AxiosPromise<Menu[]> {
|
||||
return request({
|
||||
url: '/api/v1/menus',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单下拉树形列表
|
||||
*/
|
||||
export function listMenuOptions(): AxiosPromise<Menu[]> {
|
||||
return request({
|
||||
url: '/api/v1/menus/options',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取资源(菜单+权限)树形列表
|
||||
*/
|
||||
export function listResources(): AxiosPromise<Resource[]> {
|
||||
return request({
|
||||
url: '/api/v1/menus/resources',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取菜单详情
|
||||
* @param id
|
||||
*/
|
||||
export function getMenuDetail(id: string): AxiosPromise<MenuForm> {
|
||||
return request({
|
||||
url: '/api/v1/menus/' + id,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加菜单
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
export function addMenu(data: MenuForm) {
|
||||
return request({
|
||||
url: '/api/v1/menus',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改菜单
|
||||
*
|
||||
* @param id
|
||||
* @param data
|
||||
*/
|
||||
export function updateMenu(id: string, data: MenuForm) {
|
||||
return request({
|
||||
url: '/api/v1/menus/' + id,
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除菜单
|
||||
*
|
||||
* @param ids 菜单ID,多个以英文逗号(,)分割
|
||||
*/
|
||||
export function deleteMenus(ids: string) {
|
||||
return request({
|
||||
url: '/api/v1/menus/' + ids,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
105
frontend-sjgl/src/api/menu/types.ts
Normal file
@ -0,0 +1,105 @@
|
||||
/**
|
||||
* 菜单查询参数类型声明
|
||||
*/
|
||||
export interface MenuQuery {
|
||||
keywords?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单分页列表项声明
|
||||
*/
|
||||
|
||||
export interface Menu {
|
||||
id?: number;
|
||||
parentId: number;
|
||||
type?: string | 'CATEGORY' | 'MENU' | 'EXTLINK';
|
||||
createTime: string;
|
||||
updateTime: string;
|
||||
name: string;
|
||||
icon: string;
|
||||
component: string;
|
||||
sort: number;
|
||||
visible: number;
|
||||
children: Menu[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 菜单表单类型声明
|
||||
*/
|
||||
export interface MenuForm {
|
||||
/**
|
||||
* 菜单ID
|
||||
*/
|
||||
id?: string;
|
||||
/**
|
||||
* 父菜单ID
|
||||
*/
|
||||
parentId: string;
|
||||
/**
|
||||
* 菜单名称
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* 菜单是否可见(1:是;0:否;)
|
||||
*/
|
||||
visible: number;
|
||||
icon?: string;
|
||||
/**
|
||||
* 排序
|
||||
*/
|
||||
sort: number;
|
||||
/**
|
||||
* 组件路径
|
||||
*/
|
||||
component?: string;
|
||||
/**
|
||||
* 路由路径
|
||||
*/
|
||||
path: string;
|
||||
/**
|
||||
* 跳转路由路径
|
||||
*/
|
||||
redirect?: string;
|
||||
|
||||
/**
|
||||
* 菜单类型
|
||||
*/
|
||||
type: string;
|
||||
|
||||
/**
|
||||
* 权限标识
|
||||
*/
|
||||
perm?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 资源(菜单+权限)类型
|
||||
*/
|
||||
export interface Resource {
|
||||
/**
|
||||
* 菜单值
|
||||
*/
|
||||
value: string;
|
||||
/**
|
||||
* 菜单文本
|
||||
*/
|
||||
label: string;
|
||||
/**
|
||||
* 子菜单
|
||||
*/
|
||||
children: Resource[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限类型
|
||||
*/
|
||||
export interface Permission {
|
||||
/**
|
||||
* 权限值
|
||||
*/
|
||||
value: string;
|
||||
/**
|
||||
* 权限文本
|
||||
*/
|
||||
label: string;
|
||||
}
|
||||
18
frontend-sjgl/src/api/record/index.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
//获取所有角色
|
||||
export function getLogList(params:any){
|
||||
return request({
|
||||
url: '/system/log/getLogList' ,
|
||||
method: 'post',
|
||||
params: params
|
||||
});
|
||||
}
|
||||
export function exportExcel(queryParams: any) {
|
||||
return request({
|
||||
url: '/system/log/exportExcel',
|
||||
method: 'get',
|
||||
params: queryParams,
|
||||
responseType: 'arraybuffer'
|
||||
});
|
||||
}
|
||||
196
frontend-sjgl/src/api/role/index.ts
Normal file
@ -0,0 +1,196 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { RoleQuery, RoleForm } from './types';
|
||||
|
||||
//获取所有角色
|
||||
export function listRolePages(queryParams:any){
|
||||
return request({
|
||||
url: '/system/role/list' ,
|
||||
method: 'post',
|
||||
params:queryParams
|
||||
});
|
||||
}
|
||||
//角色是否有效
|
||||
export function isvaildTo(queryParams:any){
|
||||
return request({
|
||||
url: '/system/role/setIsvaild' ,
|
||||
method: 'post',
|
||||
params:queryParams
|
||||
});
|
||||
}
|
||||
//新增角色
|
||||
export function addDept(queryParams:any){
|
||||
return request({
|
||||
url:'/system/role/addRole' ,
|
||||
method: 'post',
|
||||
data: queryParams
|
||||
});
|
||||
}
|
||||
//更新角色信息
|
||||
export function renewDept (queryParams:any){
|
||||
return request({
|
||||
url:'/system/role/updateById' ,
|
||||
method: 'post',
|
||||
data: queryParams
|
||||
});
|
||||
}
|
||||
//单个删除角色
|
||||
export function deleDept (queryParams:any){
|
||||
return request({
|
||||
url:'/system/role/deleteById' ,
|
||||
method: 'post',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
|
||||
//获取分配权限
|
||||
export function assignmentPer (queryParams:any){
|
||||
return request({
|
||||
url:'/system/menu/permissionAssignment' ,
|
||||
method: 'post',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
//发出分配权限
|
||||
export function setMenuById (queryParams:any){
|
||||
return request({
|
||||
url:'/system/role/setMenuById' ,
|
||||
method: 'post',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
////获取组织范围
|
||||
export function setOrgscope (queryParams:any){
|
||||
return request({
|
||||
url:'/system/organization/getOrgScopeTree' ,
|
||||
method: 'post',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
//修改组织范围
|
||||
export function postOrgscope (queryParams:any){
|
||||
return request({
|
||||
url:'/system/role/setOrgscope' ,
|
||||
method: 'post',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//删除角色
|
||||
// export function delDept(queryParams:any){
|
||||
// return request({
|
||||
// url:'/system/role/addRole' ,
|
||||
// method: 'post',
|
||||
// data: queryParams
|
||||
// });
|
||||
// }
|
||||
|
||||
/**
|
||||
* 获取角色分页数据
|
||||
*
|
||||
* @param queryParam
|
||||
*/
|
||||
// export function listRolePages(
|
||||
// queryParams?: RoleQuery
|
||||
// ): AxiosPromise<RolePageResult> {
|
||||
// return request({
|
||||
// url: '/system/role/list',
|
||||
// method: 'post',
|
||||
// params: queryParams
|
||||
// });
|
||||
// }
|
||||
|
||||
/**
|
||||
* 获取角色下拉数据
|
||||
*
|
||||
* @param queryParams
|
||||
*/
|
||||
export function listRoleOptions(
|
||||
queryParams?: RoleQuery
|
||||
): AxiosPromise<any[]> {
|
||||
return request({
|
||||
url: '/api/v1/roles/options',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取角色拥有的资源ID集合
|
||||
*
|
||||
* @param queryParams
|
||||
*/
|
||||
export function getRoleMenuIds(roleId: string): AxiosPromise<number[]> {
|
||||
return request({
|
||||
url: '/api/v1/roles/' + roleId + '/menuIds',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改角色资源权限
|
||||
*
|
||||
* @param queryParams
|
||||
*/
|
||||
export function updateRoleMenus(
|
||||
roleId: string,
|
||||
data: number[]
|
||||
): AxiosPromise<any> {
|
||||
return request({
|
||||
url: '/api/v1/roles/' + roleId + '/menus',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取角色详情
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
export function getRoleDetail(id: number): AxiosPromise<RoleForm> {
|
||||
return request({
|
||||
url: '/api/v1/roles/' + id,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加角色
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
export function addRole(data: RoleForm) {
|
||||
return request({
|
||||
url: '/api/v1/roles',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新角色
|
||||
*
|
||||
* @param id
|
||||
* @param data
|
||||
*/
|
||||
export function updateRole(id: number, data: RoleForm) {
|
||||
return request({
|
||||
url: '/api/v1/roles/' + id,
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除角色,多个以英文逗号(,)分割
|
||||
*
|
||||
* @param ids
|
||||
*/
|
||||
export function deleteRoles(ids: string) {
|
||||
return request({
|
||||
url: '/api/v1/roles/' + ids,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
47
frontend-sjgl/src/api/role/types.ts
Normal file
@ -0,0 +1,47 @@
|
||||
/**
|
||||
* 角色查询参数类型
|
||||
*/
|
||||
interface PageQuery {
|
||||
pageIndex: number;
|
||||
pageSize: number;
|
||||
}
|
||||
export interface RoleQuery extends PageQuery {
|
||||
keywords?: string;
|
||||
}
|
||||
interface PageResult<T> {
|
||||
total: number;
|
||||
list: T[];
|
||||
}
|
||||
/**
|
||||
* 角色分页列表项
|
||||
*/
|
||||
export interface Role {
|
||||
id: string;
|
||||
name: string;
|
||||
code: string;
|
||||
sort: number;
|
||||
status: number;
|
||||
deleted: number;
|
||||
menuIds?: any;
|
||||
permissionIds?: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色分页项类型
|
||||
*/
|
||||
export type RolePageResult = PageResult<Role[]>;
|
||||
|
||||
/**
|
||||
* 角色表单
|
||||
*/
|
||||
export interface RoleForm {
|
||||
id?: number;
|
||||
name: string;
|
||||
code: string;
|
||||
sort: number;
|
||||
status: number;
|
||||
/**
|
||||
* 数据权限
|
||||
*/
|
||||
dataScope: number;
|
||||
}
|
||||
132
frontend-sjgl/src/api/select/index.ts
Normal file
@ -0,0 +1,132 @@
|
||||
import request from '@/utils/request';
|
||||
//水电基地数据获取
|
||||
export function wbsbGetKendoList(data: any) {
|
||||
return request({
|
||||
url: '/env/hydrobase/wbsb/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 基地下拉列表
|
||||
export function getBaseDropdown(data: any) {
|
||||
return request({
|
||||
url: '/env/hydrobase/dropdown',
|
||||
method: 'get',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 流域下拉列表
|
||||
export function getSelectForDropdown(data: any) {
|
||||
return request({
|
||||
// url: '/env/rvcd/selectForDropdown',
|
||||
url: '/env/rvcd/selectRvcdDropdown',
|
||||
method: 'get',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 所在河段下拉列表
|
||||
export function getRvcdDropdown(params: any) {
|
||||
return request({
|
||||
url: '/env/rvcd/selectForDropdown',
|
||||
method: 'get',
|
||||
params: params
|
||||
});
|
||||
}
|
||||
//电站下拉列表
|
||||
export function getEngInfoDropdown(data: any) {
|
||||
return request({
|
||||
url: '/env/engInfo/dropdown',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 根据河段获取电站
|
||||
export function getByRvcd(data: any) {
|
||||
return request({
|
||||
url: '/env/engInfo/getByRvcd',
|
||||
method: 'get',
|
||||
params:data
|
||||
});
|
||||
}
|
||||
// 根据id获取电站信息
|
||||
export function getEngInfoById(params: any) {
|
||||
return request({
|
||||
url: '/env/engInfo/getById',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
// 所在位置下拉列表
|
||||
export function getAddvcdDropdown(data: any) {
|
||||
return request({
|
||||
url: '/env/addvcd/selectForDropdown',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 重新验证并更新行数据
|
||||
export function revalidateAndUpdateRow(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/revalidateAndUpdateRow',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 删除 行数据
|
||||
export function deleteRowById(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/deleteRowById',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
//过鱼设施下拉列表
|
||||
export function getFpssDropdown(params: any) {
|
||||
return request({
|
||||
url: '/env/fpss/dropdown',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
//鱼类名称下拉列表
|
||||
export function getFishDictoryDropdown() {
|
||||
return request({
|
||||
url: '/env/fishDictory/listByName',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
// 类似鱼类名称下拉列表
|
||||
export function getSimilarFishDictoryDropdown(params: any) {
|
||||
return request({
|
||||
url: '/env/fishDictory/similar',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
// 上传文件
|
||||
export function uploadFile(data: any) {
|
||||
return request({
|
||||
url: import.meta.env.VITE_APP_ATTACHMENT_URL + '/upload',
|
||||
method: 'post',
|
||||
data,
|
||||
headers: { 'Content-Type': 'multipart/form-data' }
|
||||
});
|
||||
}
|
||||
// 所在位置下拉列表
|
||||
export function getAddvcdDropdownByRvcd(data: any = {}) {
|
||||
return request({
|
||||
url: '/base/msalongb/noAuth/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//沿程配置下拉列表
|
||||
export function noAuthGetKendoPage(data: any = {}) {
|
||||
return request({
|
||||
url: '/base/msalongb/noAuth/GetKendoPage',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
45
frontend-sjgl/src/api/shengPiJiLu/index.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
export function queryPageList(queryParams:any){
|
||||
return request({
|
||||
url: '/data/approvalMain/queryPageList' ,
|
||||
method: 'post',
|
||||
data:queryParams
|
||||
});
|
||||
}
|
||||
|
||||
// 查询审批操作日志列表
|
||||
export function getApprovalLogList(params: any) {
|
||||
return request({
|
||||
url: '/data/approvalLog/queryPageList',
|
||||
method: 'post',
|
||||
data: params
|
||||
});
|
||||
}
|
||||
|
||||
// 查询审批变更记录列表
|
||||
export function getApprovalChangeLogList(params: any) {
|
||||
return request({
|
||||
url: '/data/approvalChangeLog/queryPageList',
|
||||
method: 'post',
|
||||
data: params
|
||||
});
|
||||
}
|
||||
|
||||
// 批量审批
|
||||
export function batchApproveByApprovalId(data: any) {
|
||||
return request({
|
||||
url: '/data/fishDraft/batchApproveByApprovalId',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
// 批量驳回
|
||||
export function batchReject(data: { approvalIds: string[], rejectReason: string }) {
|
||||
return request({
|
||||
url: '/data/fishDraft/batchReject',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
25
frontend-sjgl/src/api/shiPinJianKong/index.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import request from '@/utils/request';
|
||||
// 顶部tabs
|
||||
export function baseMsstbprpt(data: any) {
|
||||
return request({
|
||||
url: '/vd/msstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 实时视频
|
||||
export function envVdTreeGetKendoListCust(data: any) {
|
||||
return request({
|
||||
url: '/vd/tree/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 录像
|
||||
export function envVdRunDataGetKendoList(data: any) {
|
||||
return request({
|
||||
url: '/vd/runData/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
154
frontend-sjgl/src/api/sw/index.ts
Normal file
@ -0,0 +1,154 @@
|
||||
import request from '@/utils/request';
|
||||
export function getKendoListCust(data: any) {
|
||||
return request({
|
||||
url: '/wt/alongList/qgc/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//获取水温下拉框
|
||||
export function wbsbGetKendoList(data: any) {
|
||||
return request({
|
||||
url: '/wt/wbsb/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 获取垂向水温变化树形站点数据
|
||||
* @param data 请求参数
|
||||
* @returns Promise
|
||||
*/
|
||||
export function getChuiXiangShuiWenTreeStcd(data: any) {
|
||||
return request({
|
||||
url: '/wt/sdrvwts/default/treeStcd',
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取垂向水温变化列表数据(按月份聚合)
|
||||
* @param data 请求参数 { filter, sort }
|
||||
* @returns Promise
|
||||
*/
|
||||
export function getCxswList(data: any) {
|
||||
return request({
|
||||
url: '/wt/dzCxList/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//获取出入库水温下拉选则树
|
||||
export function getVmsstbprpt(data: any) {
|
||||
return request({
|
||||
url: '/eq/vmsstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//出入库水温图表数据
|
||||
//
|
||||
export function inOutOneGetKendoListCust(data: any) {
|
||||
return request({
|
||||
url: '/wt/inOutOne/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//水温监测工作开展情况
|
||||
export function baseEvnmAutoMonitorGetKendoListCust(data: any) {
|
||||
return request({
|
||||
url: '/wt/evnmAutoMonitor/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
////水温监测工作开展情况弹框
|
||||
export function vmsstbprptGetKendoList(data: any) {
|
||||
return request({
|
||||
url: '/wt/vmsstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//出入库水温打开弹框api/wmp-env-server/sw/inOutOne/details
|
||||
export function inOutOneDetails(data: any) {
|
||||
return request({
|
||||
url: '/wt/inOutOne/details',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//鱼类适宜性分析 - select
|
||||
export function infoGetKendoListCust(data: any) {
|
||||
return request({
|
||||
url: '/wt/wtrv/fish/info/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//鱼类适宜性分析-图表和table
|
||||
export function fishGetKendoListCust(data: any) {
|
||||
return request({
|
||||
url: '/wt/wtrv/fish/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//月平均水温历史对比
|
||||
export function avgMonGetKendoListCust(data: any) {
|
||||
return request({
|
||||
url: '/wt/monthList/avgMon/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//水温年内分布
|
||||
export function yearListGetKendoListCust(data: any) {
|
||||
return request({
|
||||
url: '/wt/yearList/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//设施类型介绍
|
||||
export function sttpbGetKendoList(data: any) {
|
||||
return request({
|
||||
url: '/wt/sttpb/GetKendoList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//设施类型及接入情况
|
||||
export function dwInfoGetKendoListCust(data: any) {
|
||||
return request({
|
||||
url: '/wt/dwInfo/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//月均水温对比,图表,表格
|
||||
export function DetGetKendoListCust(data: any) {
|
||||
return request({
|
||||
url: '/wt/monthDetail/Det/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//水温年内分布
|
||||
export function yearDetailGetKendoListCust(data: any) {
|
||||
return request({
|
||||
url: '/wt/yearDetail/GetKendoListCust',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//获取建设状态
|
||||
export function dictgetRemoteDictValue(data: any) {
|
||||
return request({
|
||||
url: '/wt/usm/v1/dict/getRemoteDictValue',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
26
frontend-sjgl/src/api/system/alertRules/index.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 获取所有倾斜摄影
|
||||
export function warnruleGetKendoList(data: any) {
|
||||
return request({
|
||||
url: '/api/wmp-sys-server/sys/warn/rule/GetKendoList',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
//预警类型下拉框 //水质等级下拉框
|
||||
export function dictGetRemoteDictValue(data: any) {
|
||||
return request({
|
||||
url: '/api/dec-modules-usm-springcloud-starter/usm/v1/dict/getRemoteDictValue',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
//新增修改获取相关输入数据
|
||||
export function ruleysList(data: any) {
|
||||
return request({
|
||||
url: '/api/wmp-sys-server/sys/warn/rule/ysList',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
50
frontend-sjgl/src/api/system/disposeManage/index.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 飞行路径
|
||||
export function threedroambGetKendoListCust(data: any) {
|
||||
return request({
|
||||
url: '/threedroamb/GetKendoListCust',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
export function threedroambsave(data: any) {
|
||||
return request({
|
||||
url: '/threedroamb/save',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
export function threedroambdelete(data: any) {
|
||||
return request({
|
||||
url: '/threedroamb/delete',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
//根据id查询弹窗
|
||||
export function threedroambGetKendoById(data: any) {
|
||||
return request({
|
||||
url: '/threedroamb/getThreedRoamDetails',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
// 导入接口
|
||||
export function threedroambimport(data: FormData) {
|
||||
return request({
|
||||
url: '/threedroamb/import',
|
||||
method: 'post',
|
||||
data: data,
|
||||
headers: { 'Content-Type': 'multipart/form-data' }
|
||||
});
|
||||
}
|
||||
// 导出模板
|
||||
export function threedroambexport(data: any) {
|
||||
return request({
|
||||
url: '/threedroamb/export',
|
||||
method: 'post',
|
||||
data: data,
|
||||
responseType: 'blob'
|
||||
});
|
||||
}
|
||||
59
frontend-sjgl/src/api/system/map/ConfigManagement/index.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 获取所有沿程配置数据
|
||||
export function getAllConfigTree(data: any) {
|
||||
return request({
|
||||
url: '/base/msalongb/GetKendoList',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
// 保存沿程配置
|
||||
export function saveBaseWbsb(data: any) {
|
||||
return request({
|
||||
url: '/base/msalongb/save',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
// 删除沿程配置
|
||||
export function deleteBaseWbsb(data: any) {
|
||||
return request({
|
||||
url: '/base/msalongb/delete',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
// 保存沿程配置子节点
|
||||
export function saveBaseWbsbChild(data: any) {
|
||||
return request({
|
||||
url: '/base/msalongb/save',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
// 查询子节点
|
||||
export function getChildConfigTree(data: any) {
|
||||
return request({
|
||||
url: '/base/msalongdetb/GetKendoList',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 保存子节点
|
||||
export function saveBaseWbsbChildDetail(data: any) {
|
||||
return request({
|
||||
url: '/base/msalongdetb/save',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
//站点类型下拉框
|
||||
export function sttpGetKendoList(data: any) {
|
||||
return request({
|
||||
url: '/base/msalongb/sttp/GetKendoList',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
26
frontend-sjgl/src/api/system/map/LayerManagement/index.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 获取所有地图 图层树
|
||||
export function getAllMapLayerTree(data: any) {
|
||||
return request({
|
||||
url: '/mapLayer/getAllMapLayerTree',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
// 保存地图 图层
|
||||
export function saveMapLayer(data: any) {
|
||||
return request({
|
||||
url: '/mapLayer/save',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
// 删除地图 图层
|
||||
export function deleteMapLayer(data: any) {
|
||||
return request({
|
||||
url: '/mapLayer/delete',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
60
frontend-sjgl/src/api/system/map/LegendStructure/index.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 获取所有地图 图例树
|
||||
export function getAllMapLegendTree(data: any) {
|
||||
return request({
|
||||
url: '/mapLegend/GetKendoList',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
// 选中配置 列表
|
||||
export function getAllMapLegendModuleTree(data: any) {
|
||||
return request({
|
||||
url: '/mapmodule/GetKendoList',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
// 选中配置 新增
|
||||
export function saveMapLegendModule(data: any) {
|
||||
return request({
|
||||
url: '/mapmodule/save',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
// 选中配置 删除
|
||||
export function deleteMapLegendModule(data: any) {
|
||||
return request({
|
||||
url: '/mapmodule/delete',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 保存地图 图例
|
||||
export function saveMapLegend(data: any) {
|
||||
return request({
|
||||
url: '/mapLegend/save',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
// 删除地图 图例
|
||||
export function deleteMapLegend(data: any) {
|
||||
return request({
|
||||
url: '/mapLegend/delete',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
// 获取所有地图 图例树
|
||||
export function getAllMapLegendParentIdTree(data: any) {
|
||||
return request({
|
||||
url: '/mapLegend/getAllMapLegendTree',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 获取倾斜摄影 列表
|
||||
export function getListTiltPhotoTree(data: any) {
|
||||
return request({
|
||||
url: '/sys/oblique/GetKendoListCust',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
// 获取所有倾斜摄影
|
||||
export function getAllTiltPhotoTree(data: any) {
|
||||
return request({
|
||||
url: '/overview/vmsstbprpt/GetKendoList',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
// 保存倾斜摄影
|
||||
export function saveTiltPhoto(data: any) {
|
||||
return request({
|
||||
url: '/sys/oblique/addOrUpdate',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
// 删除倾斜摄影
|
||||
export function deleteTiltPhoto(data: any) {
|
||||
return request({
|
||||
url: '/sys/oblique/delete',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
}
|
||||
100
frontend-sjgl/src/api/system/map/pushManagement/index.ts
Normal file
@ -0,0 +1,100 @@
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 获取列表
|
||||
export function getPushConfigList(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/getPushConfigList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//新增推送配置
|
||||
export function addPushConfig(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/addPushConfig',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
//修改新增配置
|
||||
export function deletePushConfig(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/deletePushConfig',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//删除新增配置
|
||||
export function updatePushConfig(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/updatePushConfig',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//推送目标配置 --用户
|
||||
export function queryUsersList(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/queryUsersList',
|
||||
method: 'get',
|
||||
params:data
|
||||
});
|
||||
}
|
||||
//推送目标配置 -- 角色
|
||||
export function queryRolesList(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/queryRolesList',
|
||||
method: 'get',
|
||||
params:data
|
||||
});
|
||||
}
|
||||
//查询推送目标
|
||||
export function getPushTargets(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/getPushTargets',
|
||||
method: 'get',
|
||||
params:data
|
||||
});
|
||||
}
|
||||
//新增推送目标
|
||||
export function savePushTargets(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/savePushTargets',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//短信提醒状态修改
|
||||
export function setPushConfigSmsSwitch(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/setPushConfigSmsSwitch',
|
||||
method: 'post',
|
||||
params:data
|
||||
});
|
||||
}
|
||||
//获取推送历史列表
|
||||
export function postPushHistoryList(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/postPushHistoryList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
//推送情况
|
||||
export function getPushHistoryDetailList(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/getPushHistoryDetailList',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
//s数量
|
||||
export function getPushHistoryDetailById(data: any) {
|
||||
return request({
|
||||
url: '/system/pushConfig/getPushHistoryDetailById',
|
||||
method: 'get',
|
||||
params:data
|
||||
});
|
||||
}
|
||||
279
frontend-sjgl/src/api/user/index.ts
Normal file
@ -0,0 +1,279 @@
|
||||
import request from '@/utils/request';
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { UserForm, UserInfo, UserPageResult, UserQuery } from './types';
|
||||
//获取企业树 数据
|
||||
export function getTreelist(queryParams:any) {
|
||||
return request({
|
||||
url: '/system/organization/getOrgTree',
|
||||
method: 'POST',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
//获取用户列表信息
|
||||
export function gettableData(queryParams:any) {
|
||||
return request({
|
||||
url: '/system/user/queryUsers',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
// 审核用户列表
|
||||
export function queryPendingAuditUsers(queryParams:any) {
|
||||
return request({
|
||||
url: '/system/user/queryPendingAuditUsers',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
//用户-禁用,启用
|
||||
export function DataStatus (queryParams:any) {
|
||||
return request({
|
||||
url: '/system/user/setStatus',
|
||||
method: 'POST',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
//删除用户
|
||||
export function deltableData (queryParams:any) {
|
||||
return request({
|
||||
url: '/system/user/deleteById',
|
||||
method: 'POST',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
//批量删除
|
||||
export function delChoise (queryParams:any) {
|
||||
return request({
|
||||
url: '/system/user/deleteUserByIds',
|
||||
method: 'POST',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
//获取角色
|
||||
export function getRole (queryParams:any) {
|
||||
return request({
|
||||
url: '/system/role/list',
|
||||
method: 'POST',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
//新建用户
|
||||
export function addUsers (queryParams:any,roleids:any) {
|
||||
return request({
|
||||
url: '/system/user/addUser?'+'roleids='+roleids,
|
||||
method: 'POST',
|
||||
data: queryParams,
|
||||
});
|
||||
}
|
||||
//更改用户
|
||||
export function updataUser (queryParams:any,roleids:any) {
|
||||
return request({
|
||||
url: '/system/user/updateUser?'+'roleids='+roleids,
|
||||
method: 'POST',
|
||||
data: queryParams,
|
||||
});
|
||||
}
|
||||
//更改用户
|
||||
export function updatePersonalInfo (queryParams:any) {
|
||||
return request({
|
||||
url: '/user/updatePersonalInfo',
|
||||
method: 'POST',
|
||||
data: queryParams,
|
||||
});
|
||||
}
|
||||
//更改头像
|
||||
export function updateAvatar (data:any) {
|
||||
return request({
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
},
|
||||
url: '/system/user/updateAvatar',
|
||||
method: 'POST',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//重置密码
|
||||
export function setpass (queryParams:any) {
|
||||
return request({
|
||||
url: '/system/user/resetPassword',
|
||||
method: 'POST',
|
||||
params: queryParams,
|
||||
});
|
||||
}
|
||||
|
||||
export function updatePassword (queryParams:any) {
|
||||
return request({
|
||||
url: '/user/updatePassword',
|
||||
method: 'GET',
|
||||
params: queryParams,
|
||||
});
|
||||
}
|
||||
//获取过鱼设施权限树
|
||||
export function getFishtree(queryParams:any) {
|
||||
return request({
|
||||
url: '/env/tree/rvcdEng',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
//保存权限
|
||||
export function saveFishqvan(queryParams:any) {
|
||||
return request({
|
||||
url: '/data/userDataScope/batchAdd',
|
||||
method: 'post',
|
||||
data: queryParams
|
||||
});
|
||||
}
|
||||
//查询用户有效权限
|
||||
export function getuserdata(queryParams:any) {
|
||||
return request({
|
||||
url: '/data/userDataScope/getValidPermissions',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
|
||||
// 审计用户(审批通过/驳回)
|
||||
export function auditUser(data: any) {
|
||||
return request({
|
||||
url: '/system/user/auditUser',
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录成功后获取用户信息(昵称、头像、权限集合和角色集合)
|
||||
*/
|
||||
export function getUserInfo(): AxiosPromise<UserInfo> {
|
||||
return request({
|
||||
url: '/user/me',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户分页列表
|
||||
*
|
||||
* @param queryParams
|
||||
*/
|
||||
export function listUserPages(
|
||||
queryParams: UserQuery
|
||||
): AxiosPromise<UserPageResult> {
|
||||
return request({
|
||||
url: '/api/v1/users/pages',
|
||||
method: 'get',
|
||||
params: queryParams
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户表单详情
|
||||
*
|
||||
* @param userId
|
||||
*/
|
||||
export function getUserForm(userId: number): AxiosPromise<UserForm> {
|
||||
return request({
|
||||
url: '/api/v1/users/' + userId + '/form',
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加用户
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
export function addUser(data: any) {
|
||||
return request({
|
||||
url: '/api/v1/users',
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户
|
||||
*
|
||||
* @param id
|
||||
* @param data
|
||||
*/
|
||||
export function updateUser(id: number, data: UserForm) {
|
||||
return request({
|
||||
url: '/api/v1/users/' + id,
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户状态
|
||||
*
|
||||
* @param id
|
||||
* @param status
|
||||
*/
|
||||
export function updateUserStatus(id: number, status: number) {
|
||||
return request({
|
||||
url: '/api/v1/users/' + id + '/status',
|
||||
method: 'patch',
|
||||
params: { status: status }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改用户密码
|
||||
*
|
||||
* @param id
|
||||
* @param password
|
||||
*/
|
||||
export function updateUserPassword(id: number, password: string) {
|
||||
return request({
|
||||
url: '/api/v1/users/' + id + '/password',
|
||||
method: 'patch',
|
||||
params: { password: password }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
*
|
||||
* @param ids
|
||||
*/
|
||||
export function deleteUsers(ids: string) {
|
||||
return request({
|
||||
url: '/api/v1/users/' + ids,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载用户导入模板
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
export function downloadTemplate() {
|
||||
return request({
|
||||
url: '/api/v1/users/template',
|
||||
method: 'get',
|
||||
responseType: 'arraybuffer'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出用户
|
||||
*
|
||||
* @param queryParams
|
||||
* @returns
|
||||
*/
|
||||
export function exportUser(queryParams: UserQuery) {
|
||||
return request({
|
||||
url: '/api/v1/users/_export',
|
||||
method: 'get',
|
||||
params: queryParams,
|
||||
responseType: 'arraybuffer'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
75
frontend-sjgl/src/api/user/types.ts
Normal file
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 登录用户信息
|
||||
*/
|
||||
export interface UserInfo {
|
||||
permissions: string[];
|
||||
userInfo: any;
|
||||
nickname: string;
|
||||
avatar: string;
|
||||
roles: string[];
|
||||
perms: string[];
|
||||
}
|
||||
/**
|
||||
* 用户查询参数
|
||||
*/
|
||||
export interface PageQuery {
|
||||
keywords: string;
|
||||
status: number;
|
||||
deptId: number;
|
||||
}
|
||||
export interface UserQuery extends PageQuery {
|
||||
keywords: string;
|
||||
status: number;
|
||||
deptId: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户分页列表项声明
|
||||
*/
|
||||
export interface UserType {
|
||||
id: string;
|
||||
username: string;
|
||||
nickname: string;
|
||||
mobile: string;
|
||||
gender: number;
|
||||
avatar: string;
|
||||
email: string;
|
||||
status: number;
|
||||
deptName: string;
|
||||
roleNames: string;
|
||||
createTime: string;
|
||||
}
|
||||
|
||||
interface PageResult<T> {
|
||||
total: number;
|
||||
list: T[];
|
||||
}
|
||||
/**
|
||||
* 用户分页项类型声明
|
||||
*/
|
||||
export type UserPageResult = PageResult<any[]>;
|
||||
|
||||
/**
|
||||
* 用户表单类型声明
|
||||
*/
|
||||
export interface UserForm {
|
||||
id: number | undefined;
|
||||
deptId: number;
|
||||
username: string;
|
||||
nickname: string;
|
||||
password: string;
|
||||
mobile: string;
|
||||
email: string;
|
||||
gender: number;
|
||||
status: number;
|
||||
remark: string;
|
||||
roleIds: number[];
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户导入表单类型声明
|
||||
*/
|
||||
export interface UserImportData {
|
||||
deptId: number;
|
||||
roleIds: number[];
|
||||
}
|
||||
BIN
frontend-sjgl/src/assets/MenuIcon/czan_xz.png
Normal file
|
After Width: | Height: | Size: 160 B |
BIN
frontend-sjgl/src/assets/MenuIcon/dh_sq.png
Normal file
|
After Width: | Height: | Size: 366 B |
BIN
frontend-sjgl/src/assets/MenuIcon/dh_sq1.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
frontend-sjgl/src/assets/MenuIcon/dh_sy.png
Normal file
|
After Width: | Height: | Size: 564 B |
BIN
frontend-sjgl/src/assets/MenuIcon/dh_sy1.png
Normal file
|
After Width: | Height: | Size: 537 B |
BIN
frontend-sjgl/src/assets/MenuIcon/dh_sz.png
Normal file
|
After Width: | Height: | Size: 520 B |
BIN
frontend-sjgl/src/assets/MenuIcon/dh_sz1.png
Normal file
|
After Width: | Height: | Size: 527 B |
BIN
frontend-sjgl/src/assets/MenuIcon/dh_xm.png
Normal file
|
After Width: | Height: | Size: 677 B |
BIN
frontend-sjgl/src/assets/MenuIcon/dh_xm1.png
Normal file
|
After Width: | Height: | Size: 655 B |
BIN
frontend-sjgl/src/assets/MenuIcon/dh_xx.png
Normal file
|
After Width: | Height: | Size: 469 B |
BIN
frontend-sjgl/src/assets/MenuIcon/dh_xx1.png
Normal file
|
After Width: | Height: | Size: 462 B |
BIN
frontend-sjgl/src/assets/MenuIcon/gb.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
frontend-sjgl/src/assets/MenuIcon/grzx_tx.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
frontend-sjgl/src/assets/MenuIcon/grzx_xg.png
Normal file
|
After Width: | Height: | Size: 385 B |
BIN
frontend-sjgl/src/assets/MenuIcon/jscz_rl.png
Normal file
|
After Width: | Height: | Size: 372 B |
BIN
frontend-sjgl/src/assets/MenuIcon/jscz_sc.png
Normal file
|
After Width: | Height: | Size: 289 B |
BIN
frontend-sjgl/src/assets/MenuIcon/jscz_sc1.png
Normal file
|
After Width: | Height: | Size: 317 B |
BIN
frontend-sjgl/src/assets/MenuIcon/jscz_scdc.png
Normal file
|
After Width: | Height: | Size: 313 B |
BIN
frontend-sjgl/src/assets/MenuIcon/jscz_xz.png
Normal file
|
After Width: | Height: | Size: 156 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_an.png
Normal file
|
After Width: | Height: | Size: 401 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_an1.png
Normal file
|
After Width: | Height: | Size: 427 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_cd.png
Normal file
|
After Width: | Height: | Size: 223 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_cd1.png
Normal file
|
After Width: | Height: | Size: 233 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_czmm.png
Normal file
|
After Width: | Height: | Size: 513 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_jt.png
Normal file
|
After Width: | Height: | Size: 299 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_jt1.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_qx.png
Normal file
|
After Width: | Height: | Size: 662 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_sc.png
Normal file
|
After Width: | Height: | Size: 485 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_sc1.png
Normal file
|
After Width: | Height: | Size: 448 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_sc2.png
Normal file
|
After Width: | Height: | Size: 359 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_td.png
Normal file
|
After Width: | Height: | Size: 173 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_td1.png
Normal file
|
After Width: | Height: | Size: 171 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_td2.png
Normal file
|
After Width: | Height: | Size: 162 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_xg.png
Normal file
|
After Width: | Height: | Size: 506 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_xg1.png
Normal file
|
After Width: | Height: | Size: 460 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_xg2.png
Normal file
|
After Width: | Height: | Size: 394 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_zml.png
Normal file
|
After Width: | Height: | Size: 440 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_zml1.png
Normal file
|
After Width: | Height: | Size: 459 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_zyw.png
Normal file
|
After Width: | Height: | Size: 450 B |
BIN
frontend-sjgl/src/assets/MenuIcon/lbcz_zz.png
Normal file
|
After Width: | Height: | Size: 521 B |
BIN
frontend-sjgl/src/assets/MenuIcon/top_qp.png
Normal file
|
After Width: | Height: | Size: 425 B |
BIN
frontend-sjgl/src/assets/MenuIcon/top_qp1.png
Normal file
|
After Width: | Height: | Size: 384 B |