吉安感知网项目-前端
shuishen
2026-01-29 6dc66c2d76c74ab15c6c8f75b9804ad2adbb0785
feat:区域划分新增编辑、查看调整
4 files modified
5 files added
489 ■■■■■ changed files
applications/drone-command/env/.env.development 4 ●●●● patch | view | raw | blame | history
applications/drone-command/src/assets/images/areaMap/buffer.png patch | view | raw | blame | history
applications/drone-command/src/assets/images/areaMap/ellipse.png patch | view | raw | blame | history
applications/drone-command/src/assets/images/areaMap/polygon.png patch | view | raw | blame | history
applications/drone-command/src/assets/images/areaMap/rect.png patch | view | raw | blame | history
applications/drone-command/src/assets/images/areaMap/trash.png patch | view | raw | blame | history
applications/drone-command/src/views/api.txt 149 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue 318 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/partition/index.vue 18 ●●●● patch | view | raw | blame | history
applications/drone-command/env/.env.development
@@ -2,7 +2,7 @@
 # @Author       : yuan
 # @Date         : 2026-01-07 14:58:30
 # @LastEditors  : yuan
 # @LastEditTime : 2026-01-29 09:34:58
 # @LastEditTime : 2026-01-29 15:22:54
 # @FilePath     : \applications\drone-command\env\.env.development
 # @Description  : 
 # Copyright 2026 OBKoro1, All Rights Reserved. 
@@ -16,7 +16,7 @@
#开发环境代理地址(推荐本地新建文件 .env.development.local 来进行覆盖)
# VITE_APP_URL = https://wrj.shuixiongit.com/api
VITE_APP_URL= http://192.168.1.204
VITE_APP_URL= http://192.168.1.168
#新大屏地址
VITE_APP_DASHBOARD_URL = 'https://wrj.shuixiongit.com/command-center-dashboard/'
applications/drone-command/src/assets/images/areaMap/buffer.png
applications/drone-command/src/assets/images/areaMap/ellipse.png
applications/drone-command/src/assets/images/areaMap/polygon.png
applications/drone-command/src/assets/images/areaMap/rect.png
applications/drone-command/src/assets/images/areaMap/trash.png
applications/drone-command/src/views/api.txt
@@ -1,9 +1,9 @@
## 重点关注
## 新增或修改
**接口地址**:`/drone-fw/record/fwAlarmFavorite/save`
**接口地址**:`/area/fwAreaDivide/submit`
**请求方式**:`POST`
@@ -15,7 +15,7 @@
**响应数据类型**:`*/*`
**接口描述**:<p>传入fwAlarmFavorite</p>
**接口描述**:<p>传入主表对象与扩展面列表</p>
@@ -24,7 +24,42 @@
```javascript
{
  "alarmRecordId": 0
  "areaDivide": {
    "areaCode": "",
    "areaName": "",
    "controlLevel": "",
    "createDept": 0,
    "createTime": "",
    "createUser": 0,
    "deviceIds": "",
    "flyDateEnd": "",
    "flyDateStart": "",
    "id": 0,
    "isDeleted": 0,
    "policeStationId": 0,
    "responseMechanism": "",
    "status": 0,
    "triggerCondition": "",
    "updateTime": "",
    "updateUser": 0
  },
  "areaDivideExtList": [
    {
      "areaCode": "",
      "areaDivideId": 0,
      "areaTypeKey": "",
      "areaTypeValue": "",
      "createDept": 0,
      "createTime": "",
      "createUser": 0,
      "geomJson": "",
      "id": 0,
      "isDeleted": 0,
      "status": 0,
      "updateTime": "",
      "updateUser": 0
    }
  ]
}
```
@@ -37,8 +72,39 @@
| 参数名称 | 参数说明 | 请求类型    | 是否必须 | 数据类型 | schema |
| -------- | -------- | ----- | -------- | -------- | ------ |
|fwAlarmFavorite|告警记录关注表|body|true|FwAlarmFavorite对象|FwAlarmFavorite对象|
|&emsp;&emsp;alarmRecordId|告警记录id||false|integer(int64)||
|fwAreaDivideSubmit|fwAreaDivideSubmit|body|true|FwAreaDivideSubmitDTO|FwAreaDivideSubmitDTO|
|&emsp;&emsp;areaDivide|区域划分表||false|FwAreaDivide对象|FwAreaDivide对象|
|&emsp;&emsp;&emsp;&emsp;areaCode|区域编码||false|string||
|&emsp;&emsp;&emsp;&emsp;areaName|区域名称||false|string||
|&emsp;&emsp;&emsp;&emsp;controlLevel|管控级别:日常/重点/严密||false|string||
|&emsp;&emsp;&emsp;&emsp;createDept|创建部门||false|integer||
|&emsp;&emsp;&emsp;&emsp;createTime|创建时间||false|string||
|&emsp;&emsp;&emsp;&emsp;createUser|创建人||false|integer||
|&emsp;&emsp;&emsp;&emsp;deviceIds|关联设备ID,逗号分隔||false|string||
|&emsp;&emsp;&emsp;&emsp;flyDateEnd|可飞行日期时间-结束||false|string||
|&emsp;&emsp;&emsp;&emsp;flyDateStart|可飞行日期时间-开始||false|string||
|&emsp;&emsp;&emsp;&emsp;id|主键id||false|integer||
|&emsp;&emsp;&emsp;&emsp;isDeleted|是否已删除||false|integer||
|&emsp;&emsp;&emsp;&emsp;policeStationId|关联派出所id||false|integer||
|&emsp;&emsp;&emsp;&emsp;responseMechanism|响应机制内容||false|string||
|&emsp;&emsp;&emsp;&emsp;status|业务状态||false|integer||
|&emsp;&emsp;&emsp;&emsp;triggerCondition|触发条件||false|string||
|&emsp;&emsp;&emsp;&emsp;updateTime|更新时间||false|string||
|&emsp;&emsp;&emsp;&emsp;updateUser|更新人||false|integer||
|&emsp;&emsp;areaDivideExtList|区域划分扩展表(多面数据/多区域类型)||false|array|FwAreaDivideExt对象|
|&emsp;&emsp;&emsp;&emsp;areaCode|区域编码||false|string||
|&emsp;&emsp;&emsp;&emsp;areaDivideId|关联主表区域划分ID||false|integer||
|&emsp;&emsp;&emsp;&emsp;areaTypeKey|区域类型数字字典key||false|string||
|&emsp;&emsp;&emsp;&emsp;areaTypeValue|区域类型数字字典value||false|string||
|&emsp;&emsp;&emsp;&emsp;createDept|创建部门||false|integer||
|&emsp;&emsp;&emsp;&emsp;createTime|创建时间||false|string||
|&emsp;&emsp;&emsp;&emsp;createUser|创建人||false|integer||
|&emsp;&emsp;&emsp;&emsp;geomJson|几何JSON||false|string||
|&emsp;&emsp;&emsp;&emsp;id|主键id||false|integer||
|&emsp;&emsp;&emsp;&emsp;isDeleted|是否已删除||false|integer||
|&emsp;&emsp;&emsp;&emsp;status|业务状态||false|integer||
|&emsp;&emsp;&emsp;&emsp;updateTime|更新时间||false|string||
|&emsp;&emsp;&emsp;&emsp;updateUser|更新人||false|integer||
**响应状态**:
@@ -77,22 +143,22 @@
## 取消关注
## 详情
**接口地址**:`/drone-fw/record/fwAlarmFavorite/remove`
**接口地址**:`/area/fwAreaDivide/detail`
**请求方式**:`POST`
**请求方式**:`GET`
**请求数据类型**:`application/json`
**请求数据类型**:`application/x-www-form-urlencoded`
**响应数据类型**:`*/*`
**接口描述**:<p>传入ids</p>
**接口描述**:<p>传入id</p>
@@ -104,7 +170,7 @@
| 参数名称 | 参数说明 | 请求类型    | 是否必须 | 数据类型 | schema |
| -------- | -------- | ----- | -------- | -------- | ------ |
|ids|主键集合|query|true|string||
|id|主键id|query|true|integer(int64)||
**响应状态**:
@@ -112,8 +178,7 @@
| 状态码 | 说明 | schema |
| -------- | -------- | ----- | 
|200|OK|R|
|201|Created||
|200|OK|R«FwAreaDivideVO»|
|401|Unauthorized||
|403|Forbidden||
|404|Not Found||
@@ -125,7 +190,24 @@
| 参数名称 | 参数说明 | 类型 | schema |
| -------- | -------- | ----- |----- | 
|code|状态码|integer(int32)|integer(int32)|
|data|承载数据|object||
|data|承载数据|FwAreaDivideVO|FwAreaDivideVO|
|&emsp;&emsp;areaCode|区域编码|string||
|&emsp;&emsp;areaName|区域名称|string||
|&emsp;&emsp;controlLevel|管控级别:日常/重点/严密|string||
|&emsp;&emsp;deviceIds|关联设备ID,逗号分隔|string||
|&emsp;&emsp;flyDateEnd|可飞行日期时间-结束|string(date-time)||
|&emsp;&emsp;flyDateStart|可飞行日期时间-开始|string(date-time)||
|&emsp;&emsp;fwAreaDivideExtList|面数据|array|FwAreaDivideExtVO|
|&emsp;&emsp;&emsp;&emsp;areaCode|区域编码|string||
|&emsp;&emsp;&emsp;&emsp;areaDivideId|关联主表区域划分ID|integer||
|&emsp;&emsp;&emsp;&emsp;areaTypeKey|区域类型数字字典key|string||
|&emsp;&emsp;&emsp;&emsp;areaTypeValue|区域类型数字字典value|string||
|&emsp;&emsp;&emsp;&emsp;geomJson|几何JSON|string||
|&emsp;&emsp;&emsp;&emsp;id|主键id|integer||
|&emsp;&emsp;id|主键id|integer(int64)||
|&emsp;&emsp;policeStationId|关联派出所id|string||
|&emsp;&emsp;responseMechanism|响应机制内容|string||
|&emsp;&emsp;triggerCondition|触发条件|string||
|msg|返回消息|string||
|success|是否成功|boolean||
@@ -133,9 +215,38 @@
**响应示例**:
```javascript
{
    "code": 0,
    "data": {},
    "msg": "",
    "success": true
    "code": 200,
    "success": true,
    "data": {
        "id": "2016778024413888513",
        "areaName": "新版测试1",
        "triggerCondition": "1",
        "responseMechanism": "1",
        "controlLevel": "1",
        "policeStationId": "6000000000001",
        "deviceIds": "",
        "flyDateStart": "2026-01-29 00:00:00",
        "flyDateEnd": "2026-01-31 00:00:00",
        "areaCode": "",
        "fwAreaDivideExtList": [
            {
                "id": "21",
                "areaDivideId": "2016778024413888513",
                "areaTypeKey": "1",
                "areaTypeValue": "侦测区",
                "geomJson": "{\"id\": \"shape_1769672288759_0bdd\", \"meta\": null, \"points\": [{\"lat\": 27.131594958673237, \"lng\": 114.97629628660002, \"height\": 0, \"latitude\": 27.131594958673237, \"longitude\": 114.97629628660002}, {\"lat\": 27.08982649211561, \"lng\": 114.95070164271222, \"height\": 0, \"latitude\": 27.08982649211561, \"longitude\": 114.95070164271222}, {\"lat\": 27.078929811185212, \"lng\": 114.9933846220512, \"height\": 0, \"latitude\": 27.078929811185212, \"longitude\": 114.9933846220512}, {\"lat\": 27.107909998247127, \"lng\": 115.02860852426171, \"height\": 0, \"latitude\": 27.107909998247127, \"longitude\": 115.02860852426171}], \"areaType\": \"1\", \"drawType\": \"polygon\", \"displayPoints\": null}",
                "areaCode": ""
            },
            {
                "id": "22",
                "areaDivideId": "2016778024413888513",
                "areaTypeKey": "1",
                "areaTypeValue": "侦测区",
                "geomJson": "{\"id\": \"shape_1769672293742_947a\", \"meta\": {\"center\": {\"lat\": 27.117257447017685, \"lng\": 115.1020385237064, \"height\": 238.8343626960753}, \"semiMajor\": 6700.514105765581, \"semiMinor\": 1943.840234046766, \"majorPoint\": {\"lat\": 27.10775369958058, \"lng\": 115.168774284004, \"height\": 104.8557871185756}, \"minorPoint\": {\"lat\": 27.10046558321718, \"lng\": 115.1077128183224, \"height\": 184.11135376718033}, \"controlPoints\": [{\"lat\": 27.117257447017685, \"lng\": 115.1020385237064, \"height\": 238.8343626960753}, {\"lat\": 27.10775369958058, \"lng\": 115.168774284004, \"height\": 104.8557871185756}, {\"lat\": 27.10046558321718, \"lng\": 115.1077128183224, \"height\": 184.11135376718033}]}, \"points\": [{\"lat\": 27.117257447017685, \"lng\": 115.1020385237064, \"height\": 238.8343626960753}, {\"lat\": 27.10775369958058, \"lng\": 115.168774284004, \"height\": 104.8557871185756}, {\"lat\": 27.10046558321718, \"lng\": 115.1077128183224, \"height\": 184.11135376718033}], \"areaType\": \"1\", \"drawType\": \"ellipse\", \"displayPoints\": [{\"lat\": 27.1172411931675, \"lng\": 115.16961434879582, \"height\": 242.35137437266533, \"latitude\": 27.1172411931675, \"longitude\": 115.16961434879582}, {\"lat\": 27.11907502581333, \"lng\": 115.16924525730374, \"height\": 242.3161770455558, \"latitude\": 27.11907502581333, \"longitude\": 115.16924525730374}, {\"lat\": 27.120889115581708, \"lng\": 115.16813979957712, \"height\": 242.2121648606328, \"latitude\": 27.120889115581708, \"longitude\": 115.16813979957712}, {\"lat\": 27.12266356982587, \"lng\": 115.1663100528295, \"height\": 242.0438829806018, \"latitude\": 27.12266356982587, \"longitude\": 115.1663100528295}, {\"lat\": 27.124378919527693, \"lng\": 115.16377603274732, \"height\": 241.81868547594897, \"latitude\": 27.124378919527693, \"longitude\": 115.16377603274732}, {\"lat\": 27.12601633381306, \"lng\": 115.16056547557488, \"height\": 241.54641391722672, \"latitude\": 27.12601633381306, \"longitude\": 115.16056547557488}, {\"lat\": 27.127557827888296, \"lng\": 115.15671353542164, \"height\": 241.238967263203, \"latitude\": 27.127557827888296, \"longitude\": 115.15671353542164}, {\"lat\": 27.128986462048708, \"lng\": 115.1522624000547, \"height\": 240.9097818279928, \"latitude\": 27.128986462048708, \"longitude\": 115.1522624000547}, {\"lat\": 27.130286529493247, \"lng\": 115.14726082934388, \"height\": 240.57324405610856, \"latitude\": 27.130286529493247, \"longitude\": 115.14726082934388}, {\"lat\": 27.131443730790306, \"lng\": 115.14176362138588, \"height\": 240.24406177058316, \"latitude\": 27.131443730790306, \"longitude\": 115.14176362138588}, {\"lat\": 27.132445332979348, \"lng\": 115.13583101214034, \"height\": 239.93662137804984, \"latitude\": 27.132445332979348, \"longitude\": 115.13583101214034}, {\"lat\": 27.13328031145803, \"lng\": 115.12952801515418, \"height\": 239.66435911715624, \"latitude\": 27.13328031145803, \"longitude\": 115.12952801515418}, {\"lat\": 27.133939472996364, \"lng\": 115.12292370862173, \"height\": 239.43917383966289, \"latitude\": 27.133939472996364, \"longitude\": 115.12292370862173}, {\"lat\": 27.134415558431908, \"lng\": 115.1160904776194, \"height\": 239.27090697284905, \"latitude\": 27.134415558431908, \"longitude\": 115.1160904776194}, {\"lat\": 27.13470332383455, \"lng\": 115.10910321985791, \"height\": 239.16691240515263, \"latitude\": 27.13470332383455, \"longitude\": 115.10910321985791}, {\"lat\": 27.134799599179868, \"lng\": 115.1020385237064, \"height\": 239.131735087732, \"latitude\": 27.134799599179868, \"longitude\": 115.1020385237064}, {\"lat\": 27.13470332383455, \"lng\": 115.09497382755488, \"height\": 239.16691240471368, \"latitude\": 27.13470332383455, \"longitude\": 115.09497382755488}, {\"lat\": 27.134415558431908, \"lng\": 115.08798656979342, \"height\": 239.27090697166375, \"latitude\": 27.134415558431908, \"longitude\": 115.08798656979342}, {\"lat\": 27.133939472996364, \"lng\": 115.08115333879108, \"height\": 239.43917384027625, \"latitude\": 27.133939472996364, \"longitude\": 115.08115333879108}, {\"lat\": 27.13328031145803, \"lng\": 115.0745490322586, \"height\": 239.66435911740945, \"latitude\": 27.13328031145803, \"longitude\": 115.0745490322586}, {\"lat\": 27.132445332979348, \"lng\": 115.0682460352724, \"height\": 239.9366213773679, \"latitude\": 27.132445332979348, \"longitude\": 115.0682460352724}, {\"lat\": 27.1314437307903, \"lng\": 115.06231342602688, \"height\": 240.24406177080297, \"latitude\": 27.1314437307903, \"longitude\": 115.06231342602688}, {\"lat\": 27.130286529493247, \"lng\": 115.0568162180689, \"height\": 240.57324405754517, \"latitude\": 27.130286529493247, \"longitude\": 115.0568162180689}, {\"lat\": 27.128986462048708, \"lng\": 115.0518146473581, \"height\": 240.9097818281966, \"latitude\": 27.128986462048708, \"longitude\": 115.0518146473581}, {\"lat\": 27.127557827888293, \"lng\": 115.04736351199114, \"height\": 241.238967262521, \"latitude\": 27.127557827888293, \"longitude\": 115.04736351199114}, {\"lat\": 27.126016333813062, \"lng\": 115.04351157183788, \"height\": 241.54641391765136, \"latitude\": 27.126016333813062, \"longitude\": 115.04351157183788}, {\"lat\": 27.12437891952769, \"lng\": 115.04030101466547, \"height\": 241.81868547645408, \"latitude\": 27.12437891952769, \"longitude\": 115.04030101466547}, {\"lat\": 27.122663569825875, \"lng\": 115.03776699458332, \"height\": 242.04388298107517, \"latitude\": 27.122663569825875, \"longitude\": 115.03776699458332}, {\"lat\": 27.120889115581715, \"lng\": 115.03593724783563, \"height\": 242.2121648595728, \"latitude\": 27.120889115581715, \"longitude\": 115.03593724783563}, {\"lat\": 27.119075025813327, \"lng\": 115.03483179010902, \"height\": 242.3161770439311, \"latitude\": 27.119075025813327, \"longitude\": 115.03483179010902}, {\"lat\": 27.117241193167494, \"lng\": 115.03446269861692, \"height\": 242.35137437283345, \"latitude\": 27.117241193167494, \"longitude\": 115.03446269861692}, {\"lat\": 27.11540771522819, \"lng\": 115.03483398128904, \"height\": 242.31621922677547, \"latitude\": 27.11540771522819, \"longitude\": 115.03483398128904}, {\"lat\": 27.11359467407704, \"lng\": 115.03594153443072, \"height\": 242.2122487268214, \"latitude\": 27.11359467407704, \"longitude\": 115.03594153443072}, {\"lat\": 27.111821916531323, \"lng\": 115.03777318924902, \"height\": 242.04400754760337, \"latitude\": 27.111821916531323, \"longitude\": 115.03777318924902}, {\"lat\": 27.110108837455485, \"lng\": 115.04030884666572, \"height\": 241.81884927999585, \"latitude\": 27.110108837455485, \"longitude\": 115.04030884666572}, {\"lat\": 27.10847416848657, \"lng\": 115.04352069887712, \"height\": 241.5466150531188, \"latitude\": 27.10847416848657, \"longitude\": 115.04352069887712}, {\"lat\": 27.106935774434948, \"lng\": 115.0473735351744, \"height\": 241.23920341133748, \"latitude\": 27.106935774434948, \"longitude\": 115.0473735351744}, {\"lat\": 27.10551045951957, \"lng\": 115.05182512862444, \"height\": 240.91005029162608, \"latitude\": 27.10551045951957, \"longitude\": 115.05182512862444}, {\"lat\": 27.104213785474624, \"lng\": 115.05682669933678, \"height\": 240.57354179818523, \"latitude\": 27.104213785474624, \"longitude\": 115.05682669933678}, {\"lat\": 27.10305990342386, \"lng\": 115.06232344921456, \"height\": 240.24438546029003, \"latitude\": 27.10305990342386, \"longitude\": 115.06232344921456}, {\"lat\": 27.10206140126076, \"lng\": 115.06825516231812, \"height\": 239.93696743263703, \"latitude\": 27.10206140126076, \"longitude\": 115.06825516231812}, {\"lat\": 27.10122916810148, \"lng\": 115.07455686426626, \"height\": 239.66472374787935, \"latitude\": 27.10122916810148, \"longitude\": 115.07455686426626}, {\"lat\": 27.100572277192217, \"lng\": 115.0811595334639, \"height\": 239.43955308582795, \"latitude\": 27.100572277192217, \"longitude\": 115.0811595334639}, {\"lat\": 27.10009788845782, \"lng\": 115.087990856394, \"height\": 239.2712967482805, \"latitude\": 27.10009788845782, \"longitude\": 115.087990856394}, {\"lat\": 27.099811171674233, \"lng\": 115.0949760187379, \"height\": 239.16730853166112, \"latitude\": 27.099811171674233, \"longitude\": 115.0949760187379}, {\"lat\": 27.09971525103608, \"lng\": 115.1020385237064, \"height\": 239.13213333836975, \"latitude\": 27.09971525103608, \"longitude\": 115.1020385237064}, {\"lat\": 27.099811171674233, \"lng\": 115.10910102867491, \"height\": 239.167308531655, \"latitude\": 27.099811171674233, \"longitude\": 115.10910102867491}, {\"lat\": 27.10009788845782, \"lng\": 115.11608619101878, \"height\": 239.27129674685, \"latitude\": 27.10009788845782, \"longitude\": 115.11608619101878}, {\"lat\": 27.10057227719222, \"lng\": 115.1229175139489, \"height\": 239.43955308551512, \"latitude\": 27.10057227719222, \"longitude\": 115.1229175139489}, {\"lat\": 27.10122916810148, \"lng\": 115.12952018314652, \"height\": 239.66472374829976, \"latitude\": 27.10122916810148, \"longitude\": 115.12952018314652}, {\"lat\": 27.10206140126076, \"lng\": 115.13582188509464, \"height\": 239.93696743312785, \"latitude\": 27.10206140126076, \"longitude\": 115.13582188509464}, {\"lat\": 27.10305990342386, \"lng\": 115.14175359819826, \"height\": 240.2443854608264, \"latitude\": 27.10305990342386, \"longitude\": 115.14175359819826}, {\"lat\": 27.104213785474617, \"lng\": 115.14725034807596, \"height\": 240.5735417970414, \"latitude\": 27.104213785474617, \"longitude\": 115.14725034807596}, {\"lat\": 27.105510459519557, \"lng\": 115.15225191878834, \"height\": 240.91005029170333, \"latitude\": 27.105510459519557, \"longitude\": 115.15225191878834}, {\"lat\": 27.106935774434948, \"lng\": 115.15670351223838, \"height\": 241.23920341122712, \"latitude\": 27.106935774434948, \"longitude\": 115.15670351223838}, {\"lat\": 27.10847416848657, \"lng\": 115.16055634853564, \"height\": 241.5466150535108, \"latitude\": 27.10847416848657, \"longitude\": 115.16055634853564}, {\"lat\": 27.110108837455485, \"lng\": 115.16376820074704, \"height\": 241.81884927874424, \"latitude\": 27.110108837455485, \"longitude\": 115.16376820074704}, {\"lat\": 27.11182191653132, \"lng\": 115.16630385816376, \"height\": 242.04400754640932, \"latitude\": 27.11182191653132, \"longitude\": 115.16630385816376}, {\"lat\": 27.11359467407704, \"lng\": 115.16813551298206, \"height\": 242.2122487283748, \"latitude\": 27.11359467407704, \"longitude\": 115.16813551298206}, {\"lat\": 27.11540771522819, \"lng\": 115.16924306612378, \"height\": 242.31621922659275, \"latitude\": 27.11540771522819, \"longitude\": 115.16924306612378}]}",
                "areaCode": ""
            }
        ]
    },
    "msg": "操作成功"
}
```
applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
@@ -1,72 +1,61 @@
<template>
    <el-dialog class="command-page-map-view-dialog" v-model="visible" :show-close="false"
        :close-on-click-modal="false">
    <el-dialog class="command-page-map-view-dialog" v-model="visible" :show-close="false" :close-on-click-modal="false">
        <div class="dialog-container">
            <div class="left-container">
                <CommonCesiumMap
                    ref="mapRef"
                    class="leftMap command-cesium"
                    :active="visible"
                    :flat-mode="false"
                    :terrain="true"
                    :layer-mode="4"
                    :boundary="false"
                />
                <div
                    v-if="showTypePanel && !readonly"
                    class="shape-type-panel"
                >
                <CommonCesiumMap ref="mapRef" class="leftMap command-cesium" :active="visible" :flat-mode="false"
                    :terrain="true" :layer-mode="4" :boundary="false" />
                <div v-if="showTypePanel && !readonly" class="shape-type-panel">
                    <div class="panel-header">
                        <span>{{ drawTypeLabelMap[currentShapeType] || '区域' }}</span>
                        <el-icon class="panel-close" @click.stop="handleTypePanelClose"><Close /></el-icon>
                        <el-icon class="panel-close" @click.stop="handleTypePanelClose">
                            <Close />
                        </el-icon>
                    </div>
                    <div class="panel-body">
                        <span class="panel-label">区域类型</span>
                        <el-select
                            class="command-select"
                            popper-class="command-select-popper"
                            v-model="activeAreaType"
                            placeholder="请选择"
                            @change="handleAreaTypeChange"
                        >
                            <el-option
                                v-for="item in dictObj.areaType"
                                :key="item.dictKey"
                                :label="item.dictValue"
                                :value="item.dictKey"
                            />
                        <el-select class="command-select" popper-class="command-select-popper" v-model="activeAreaType"
                            placeholder="请选择" @change="handleAreaTypeChange">
                            <el-option v-for="item in dictObj.areaType" :key="item.dictKey" :label="item.dictValue"
                                :value="item.dictKey" />
                        </el-select>
                    </div>
                </div>
                <div class="map-toolbar">
                    <button class="tool-btn" type="button" @click="handleDraw('polygon')">
                        <span class="tool-icon polygon"></span>
                        <span class="tool-text">多边形</span>
                    </button>
                    <button class="tool-btn" type="button" @click="handleDraw('rectangle')">
                        <span class="tool-icon rect"></span>
                        <span class="tool-text">矩形</span>
                    </button>
                    <button class="tool-btn" type="button" @click="handleDraw('ellipse')">
                        <span class="tool-icon ellipse"></span>
                        <span class="tool-text">椭圆</span>
                    </button>
                    <button class="tool-btn" type="button" @click="handleDraw('buffer')">
                        <span class="tool-icon buffer"></span>
                        <span class="tool-text">缓冲圆</span>
                    </button>
                    <button class="tool-btn danger" type="button" @click="handleClearShape">
                        <span class="tool-icon trash"></span>
                        <span class="tool-text">删除</span>
                    </button>
                    <el-tooltip content="多边形" placement="left">
                        <button class="tool-btn" type="button" @click="handleDraw('polygon')">
                            <img class="tool-icon-image" :src="polygonIcon" alt="多边形" />
                        </button>
                    </el-tooltip>
                    <el-tooltip content="矩形" placement="left">
                        <button class="tool-btn" type="button" @click="handleDraw('rectangle')">
                            <img class="tool-icon-image" :src="rectIcon" alt="矩形" />
                        </button>
                    </el-tooltip>
                    <el-tooltip content="椭圆" placement="left">
                        <button class="tool-btn" type="button" @click="handleDraw('ellipse')">
                            <img class="tool-icon-image" :src="ellipseIcon" alt="椭圆" />
                        </button>
                    </el-tooltip>
                    <el-tooltip content="缓冲圆" placement="left">
                        <button class="tool-btn" type="button" @click="handleDraw('buffer')">
                            <img class="tool-icon-image" :src="bufferIcon" alt="缓冲圆" />
                        </button>
                    </el-tooltip>
                    <el-tooltip content="删除" placement="left">
                        <button class="tool-btn danger" type="button" @click="handleClearShape">
                            <img class="tool-icon-image" :src="trashIcon" alt="删除" />
                        </button>
                    </el-tooltip>
                </div>
            </div>
            <div class="right-container">
                <div class="header">
                    <span>{{ titleEnum[dialogMode] }}</span>
                    <el-icon class="close-btn" @click.stop="visible = false"><Close /></el-icon>
                    <el-icon class="close-btn" @click.stop="visible = false">
                        <Close />
                    </el-icon>
                </div>
                <div class="content" v-if="readonly">
@@ -100,11 +89,29 @@
                        </el-col>
                    </el-row>
                    <div class="detail-title">绘制区域列表</div>
                    <div class="command-table-container">
                        <div class="command-table-content">
                            <el-table class="command-table" :data="shapeList" row-key="id">
                                <el-table-column prop="areaType" label="类型">
                                    <template v-slot="{ row }">
                                        {{ getDictLabel(row.areaType, dictObj.areaType) }}
                                    </template>
                                </el-table-column>
                                <el-table-column prop="drawType" label="绘制类型">
                                    <template v-slot="{ row }">
                                        {{ drawTypeLabelMap[row.drawType] || '-' }}
                                    </template>
                                </el-table-column>
                            </el-table>
                        </div>
                    </div>
                    <div class="detail-title">关联设备</div>
                    <div class="command-table-container">
                        <div class="command-table-content">
                            <el-table class="command-table" ref="deviceTableRef" :data="deviceOptions"
                                row-key="id" @row-click="handleDeviceRowClick">
                            <el-table class="command-table" ref="deviceTableRef" :data="deviceOptions" row-key="id"
                                @row-click="handleDeviceRowClick">
                                <el-table-column prop="deviceName" label="设备名称" />
                                <el-table-column prop="deviceType" label="类型">
                                    <template v-slot="{ row }">
@@ -119,12 +126,12 @@
                <el-form class="dialog-form" v-else ref="formRef" :model="formData" :rules="rules" :disabled="readonly"
                    label-width="96px">
                    <el-form-item label="区域名称" prop="areaName">
                        <el-input class="command-input" v-model="formData.areaName" maxlength="50"
                            placeholder="请输入" clearable />
                        <el-input class="command-input" v-model="formData.areaName" maxlength="50" placeholder="请输入"
                            clearable />
                    </el-form-item>
                    <el-form-item label="响应机制" prop="responseMechanism">
                        <el-input class="command-input" v-model="formData.responseMechanism"
                            maxlength="200" placeholder="请输入" clearable />
                        <el-input class="command-input" v-model="formData.responseMechanism" maxlength="200"
                            placeholder="请输入" clearable />
                    </el-form-item>
                    <el-form-item label="触发条件" prop="triggerCondition">
                        <el-select class="command-select" popper-class="command-select-popper"
@@ -141,10 +148,9 @@
                        </el-select>
                    </el-form-item>
                    <el-form-item label="可飞行时段" prop="flyDateStart">
                        <el-date-picker class="command-date-picker"
                            popper-class="command-date-picker-popper" v-model="flyDateRange"
                            type="datetimerange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间"
                            :disabled-date="disabledFlyDate" :disabled-time="disabledFlyTime"
                        <el-date-picker class="command-date-picker" popper-class="command-date-picker-popper"
                            v-model="flyDateRange" type="datetimerange" range-separator="至" start-placeholder="开始时间"
                            end-placeholder="结束时间" :disabled-date="disabledFlyDate" :disabled-time="disabledFlyTime"
                            value-format="YYYY-MM-DD HH:mm:ss" clearable />
                    </el-form-item>
                    <el-form-item label="关联派出所" prop="policeStationId">
@@ -157,7 +163,7 @@
                    <div class="shape-table-container">
                        <div class="shape-table-title">绘制区域列表</div>
                        <el-table class="command-table" :data="shapeList" row-key="id" height="360">
                        <el-table class="command-table" :data="shapeList" row-key="id" height="auto">
                            <el-table-column prop="areaType" label="类型">
                                <template v-slot="{ row }">
                                    {{ getDictLabel(row.areaType, dictObj.areaType) }}
@@ -183,15 +189,13 @@
                                关联设备
                            </div>
                            <el-input class="command-input" v-model="searchName" placeholder="请输入"
                                clearable></el-input>
                            <el-input class="command-input" v-model="searchName" placeholder="请输入" clearable></el-input>
                        </div>
                        <el-form-item prop="deviceIds" label-width="0">
                            <el-table class="command-table" ref="deviceTableRef"
                                :data="deviceOptions.filter(item => item.deviceName.includes(searchName))" row-key="id"
                                @selection-change="handleDeviceSelectionChange"
                                @row-click="handleDeviceRowClick">
                                @selection-change="handleDeviceSelectionChange" @row-click="handleDeviceRowClick">
                                <el-table-column type="selection" width="55" :reserve-selection="true" />
                                <el-table-column prop="deviceName" label="设备名称" />
                                <el-table-column prop="deviceType" label="类型">
@@ -205,7 +209,9 @@
                </el-form>
                <div class="footer">
                    <el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button>
                    <el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' :
                        '取消'
                    }}</el-button>
                    <el-button color="#284FE3" v-if="!readonly" type="primary" :loading="submitting"
                        :disabled="submitting" @click="handleSubmit">
                        确定
@@ -233,6 +239,11 @@
import * as Cesium from 'cesium'
import { fwPoliceStationListApi } from '@/views/areaManage/precinctInfo/precinctInfoApi'
import { fwDeviceListApi } from '@/views/basicManage/deviceStock/fwDevice'
import polygonIcon from '@/assets/images/areaMap/polygon.png'
import rectIcon from '@/assets/images/areaMap/rect.png'
import ellipseIcon from '@/assets/images/areaMap/ellipse.png'
import bufferIcon from '@/assets/images/areaMap/buffer.png'
import trashIcon from '@/assets/images/areaMap/trash.png'
const initForm = () => ({
    areaName: '', // 区域名称
@@ -357,9 +368,24 @@
    if (!isValid) return
    submitting.value = true
    try {
        let str = [...pointList, pointList[0]].map(item => `${item.longitude} ${item.latitude}`).join(',')
        formData.value.geom = `POLYGON((${str}))`
        await fwAreaDivideSubmitApi(formData.value)
        const areaDivide = { ...formData.value }
        delete areaDivide.geom
        const areaDivideExtList = shapeList.value.map(shape => {
            const areaTypeKey = shape?.areaType ?? ''
            const areaTypeValue = getDictLabel(areaTypeKey, resolveAreaTypeOptions())
            return {
                id: shape?.extId,
                areaDivideId: areaDivide?.id ?? '',
                areaCode: areaDivide?.areaCode ?? '',
                areaTypeKey,
                areaTypeValue,
                geomJson: JSON.stringify(shape),
            }
        })
        await fwAreaDivideSubmitApi({
            areaDivide,
            areaDivideExtList,
        })
        const actionText = dialogMode.value === 'add' ? '新增' : '编辑'
        saveOperationLog({
            requestUri: route.path,
@@ -416,8 +442,8 @@
        nextForm.id = detail.id
    }
    formData.value = nextForm
    activeAreaType.value = detail?.areaType ?? ''
    flyDateRange.value = [formData.value.flyDateStart, formData.value.flyDateEnd].filter(Boolean)
    syncShapeListFromDetail(detail)
}
// 格式化可飞行时间段
@@ -527,7 +553,7 @@
            flat: true,
            faceForward: true,
        }),
        asynchronous: false,
        asynchronous: false
    })
}
@@ -636,7 +662,7 @@
}
function renderShapeList () {
    if (!viewer || !visible.value || readonly.value) {
    if (!viewer || !visible.value) {
        clearShapeDisplay()
        return
    }
@@ -798,13 +824,74 @@
}
function getDetectAreaTypeKey () {
    const areaTypeOptions = Array.isArray(dictObj?.value?.areaType)
        ? dictObj.value.areaType
        : dictObj?.areaType
    const areaTypeOptions = resolveAreaTypeOptions()
    if (!Array.isArray(areaTypeOptions)) return ''
    const target = areaTypeOptions.find(item => item?.dictKey === '1')
    return target?.dictKey ?? ''
}
function resolveAreaTypeOptions () {
    return Array.isArray(dictObj?.value?.areaType)
        ? dictObj.value.areaType
        : dictObj?.areaType
}
function parseGeomJson (geomJson) {
    if (!geomJson) return null
    if (typeof geomJson === 'object') return geomJson
    if (typeof geomJson !== 'string') return null
    const trimmed = geomJson.trim()
    if (!trimmed) return null
    try {
        return JSON.parse(trimmed)
    } catch (error) {
        const legacyPoints = geomAnalysis(trimmed)
        if (Array.isArray(legacyPoints) && legacyPoints.length >= 3) {
            return { drawType: 'polygon', points: legacyPoints }
        }
    }
    return null
}
function syncShapeListFromDetail (detail) {
    const extList = Array.isArray(detail?.fwAreaDivideExtList) ? detail.fwAreaDivideExtList : []
    if (!extList.length) {
        shapeList.value = []
        activeAreaType.value = ''
        currentShapeType.value = 'polygon'
        return
    }
    shapeList.value = extList.map((item, index) => {
        const isShapePayload = item?.drawType || item?.points
        if (isShapePayload) {
            return {
                id: item?.id || `shape_${Date.now()}_${index}_${Math.random().toString(16).slice(2, 6)}`,
                extId: item?.extId ?? item?.id,
                areaType: item?.areaType ?? '',
                drawType: item?.drawType ?? 'polygon',
                points: Array.isArray(item?.points) ? item.points : [],
                displayPoints: Array.isArray(item?.displayPoints) ? item.displayPoints : null,
                meta: item?.meta ?? null,
            }
        }
        const parsed = parseGeomJson(item?.geomJson) || {}
        const drawType = parsed?.drawType || 'polygon'
        const areaType = item?.areaTypeKey ?? parsed?.areaType ?? ''
        const points = Array.isArray(parsed?.points) ? parsed.points : []
        const displayPoints = Array.isArray(parsed?.displayPoints) ? parsed.displayPoints : null
        const meta = parsed?.meta ?? null
        return {
            id: parsed?.id || `shape_${Date.now()}_${index}_${Math.random().toString(16).slice(2, 6)}`,
            extId: item?.id,
            areaType,
            drawType,
            points,
            displayPoints,
            meta,
        }
    })
    activeAreaType.value = shapeList.value[0]?.areaType ?? ''
    currentShapeType.value = shapeList.value[0]?.drawType ?? 'polygon'
}
function showTypePanelAtCurrent () {
@@ -950,6 +1037,11 @@
// 查看面
function viewPolygon () {
    if (!viewer) return
    if (shapeList.value.length) {
        renderShapeList()
        return
    }
    if (!formData.value?.geom) return
    pointList = geomAnalysis(formData.value.geom)
    const result = pointList.map(item => [item.longitude, item.latitude]).flat()
@@ -1000,17 +1092,23 @@
// 同步选择状态
function syncDeviceSelection () {
    if (!deviceTableRef.value) return
    deviceTableRef.value.clearSelection()
    const rows = []
    const arr = formData.value.deviceIds.split(',')
    deviceOptions.value.forEach(row => {
        if (arr.includes(row.id)) {
            deviceTableRef.value.toggleRowSelection(row, true)
            rows.push(row)
        }
    })
    selectedDeviceRows.value = rows
    if (readonly.value) {
        renderDeviceRanges(selectedDeviceRows.value)
        return
    }
    if (!deviceTableRef.value) return
    deviceTableRef.value.clearSelection()
    rows.forEach(row => {
        deviceTableRef.value.toggleRowSelection(row, true)
    })
}
// 打开弹框
@@ -1021,6 +1119,7 @@
    shapeList.value = []
    activeShapeId.value = null
    activeAreaType.value = ''
    pointList = []
    await nextTick()
    initMap()
    clearShapeDisplay()
@@ -1033,18 +1132,6 @@
        // default no draw mode
    } else if (dialogMode.value === 'edit') {
        await loadDetail()
        pointList = geomAnalysis(formData.value.geom) || []
        if (pointList.length) {
            activeShapeId.value = `shape_${Date.now()}_${Math.random().toString(16).slice(2, 6)}`
            shapeList.value = [
                {
                    id: activeShapeId.value,
                    areaType: activeAreaType.value,
                    drawType: currentShapeType.value,
                    points: _.cloneDeep(pointList),
                },
            ]
        }
        viewPolygon()
    } else {
        await loadDetail()
@@ -1132,20 +1219,20 @@
}
.tool-btn {
    padding: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    width: 64px;
    padding: 8px 6px;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: 6px;
    border-radius: 8px;
    color: #ffffff;
    font-size: 12px;
    line-height: 1;
    cursor: pointer;
    transition: all 0.2s ease;
    overflow: hidden;
}
.tool-btn:hover {
@@ -1165,10 +1252,11 @@
.tool-icon {
    position: relative;
    width: 20px;
    height: 20px;
    border: 2px solid #ffffff;
    border-radius: 3px;
}
.tool-icon-image {
    width: 36px;
    height: 36px;
}
.tool-icon.polygon {
@@ -1216,23 +1304,21 @@
}
.shape-table-container {
    margin-top: 8px;
    padding: 8px;
    border-radius: 8px;
    background: rgba(27, 34, 56, 0.6);
}
    margin-bottom: 20px;
.shape-table-title {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    padding-right: 1.2rem;
    font-family: Source Han Sans CN, Source Han Sans CN;
    font-weight: 500;
    font-size: 1.4rem;
    color: #D4D5D7;
    font-style: normal;
    text-transform: none;
    box-sizing: border-box;
    .shape-table-title {
        margin-bottom: 20px;
        display: flex;
        align-items: center;
        justify-content: flex-start;
        padding-right: 1.2rem;
        font-family: Source Han Sans CN, Source Han Sans CN;
        font-weight: 500;
        font-size: 1.4rem;
        color: #D4D5D7;
        font-style: normal;
        text-transform: none;
        box-sizing: border-box;
    }
}
</style>
applications/drone-command/src/views/areaManage/partition/index.vue
@@ -5,7 +5,6 @@
                <el-input class="command-input" v-model="searchParams.areaName" placeholder="请输入"
                    clearable @clear="handleSearch" />
            </el-form-item>
            <el-form-item label="区域类型" prop="areaType">
                <el-select class="command-select" popper-class="command-select-popper"
                    v-model="searchParams.areaType" placeholder="请选择" clearable @change="handleSearch">
@@ -31,24 +30,18 @@
                    <el-table-column type="selection" width="46" />
                    <el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
                    <el-table-column prop="areaName" show-overflow-tooltip width="150" label="区域名称" />
                    <el-table-column show-overflow-tooltip width="160" label="区域位置">
                        <template v-slot="{ row }">
                            {{ formatLocation(row) }}
                        </template>
                    </el-table-column>
                    <el-table-column prop="areaSize" show-overflow-tooltip width="130" label="区域面积(k㎡)" />
                    <el-table-column prop="areaType" show-overflow-tooltip width="120" label="区域类型">
                        <template v-slot="{ row }">
                            {{ getDictLabel(row.areaType, dictObj.areaType) }}
                        </template>
                    </el-table-column>
                    <el-table-column prop="triggerCondition" show-overflow-tooltip width="130" label="触发条件">
                    <el-table-column prop="triggerCondition" show-overflow-tooltip label="触发条件">
                        <template v-slot="{ row }">
                            {{ getDictLabel(row.triggerCondition, dictObj.triggeringCondition) }}
                        </template>
                    </el-table-column>
                    <el-table-column prop="responseMechanism" show-overflow-tooltip width="130" label="响应机制" />
                    <el-table-column prop="controlLevel" show-overflow-tooltip width="120" label="管控级别">
                    <el-table-column prop="responseMechanism" show-overflow-tooltip label="响应机制" />
                    <el-table-column prop="controlLevel" show-overflow-tooltip label="管控级别">
                        <template v-slot="{ row }">
                            {{ getDictLabel(row.controlLevel, dictObj.controlLevel) }}
                        </template>
@@ -157,11 +150,6 @@
// 勾选值设置
function handleSelectionChange (rows) {
    selectedIds.value = rows.map(item => item.id)
}
function formatLocation (row) {
    if (row?.longitude == null || row?.latitude == null) return ''
    return `${row.longitude}, ${row.latitude}`
}
function formatFlyDate (row) {