navigation.vue 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  1. <template>
  2. <div class="main">
  3. <el-row>
  4. <el-col :xs="1" :sm="1" :md="1" :lg="1" :xl="1" style="position: relative;">
  5. <div class="main-menu">
  6. <div class="img-container" :class="{ 'active': activeIndex === 0 }" @click="openDraSetting"><img
  7. src="@/assets/icons/img/setting.png" class="notification__image" width="22px" height="22px" />
  8. <span class="notification__title">功能</span>
  9. </div>
  10. <div class="img-container" :class="{ 'active': activeIndex === 1 }" @click="openPoint"><img
  11. src="@/assets/icons/img/post.png" class="notification__image" width="22px" height="22px" />
  12. <span class="notification__title">目标点</span>
  13. </div>
  14. <div class="img-container" :class="{ 'active': activeIndex === 2 }" @click="openTask"><img
  15. src="@/assets/icons/img/task.png" class="notification__image" width="22px" height="22px" />
  16. <span class="notification__title">任务</span>
  17. </div>
  18. <div class="img-container" :class="{ 'active': activeIndex === 3 }" @click="initNavigation"><img
  19. src="@/assets/icons/img/init.png" class="notification__image" width="22px" height="22px" />
  20. <span class="notification__title">初始化</span>
  21. </div>
  22. <div class="img-container" @click="restNavigation"><img src="@/assets/icons/img/restart.png"
  23. class="notification__image" width="22px" height="22px" />
  24. <span class="notification__title">重启</span>
  25. </div>
  26. <div class="img-container" @click="offNavigation"><img src="@/assets/icons/img/off.png"
  27. class="notification__image" width="22px" height="22px" />
  28. <span class="notification__title">结束</span>
  29. </div>
  30. </div>
  31. <!-- 功能设置 -->
  32. <div class="drawer" v-show="settingDrawer" style="width: 200px;">
  33. <div style="position: relative;">
  34. <p>点云</p>
  35. <el-radio-group v-model="settingParams.pointCloud" size="mini">
  36. <el-radio-button :label="true">开</el-radio-button>
  37. <el-radio-button :label="false">关</el-radio-button>
  38. </el-radio-group>
  39. <p>底图</p>
  40. <el-radio-group v-model="settingParams.baseMap" size="mini">
  41. <el-radio-button :label="true">开</el-radio-button>
  42. <el-radio-button :label="false">关</el-radio-button>
  43. </el-radio-group>
  44. <p>点ID</p>
  45. <el-radio-group v-model="settingParams.pointId" size="mini">
  46. <el-radio-button :label="true">开</el-radio-button>
  47. <el-radio-button :label="false">关</el-radio-button>
  48. </el-radio-group>
  49. <p>位置跟随</p>
  50. <el-radio-group v-model="settingParams.follow" size="mini">
  51. <el-radio-button :label="true">开</el-radio-button>
  52. <el-radio-button :label="false">关</el-radio-button>
  53. </el-radio-group>
  54. <p>网络邻居</p>
  55. <el-radio-group v-model="settingParams.network" size="mini">
  56. <el-radio-button :label="true">开</el-radio-button>
  57. <el-radio-button :label="false">关</el-radio-button>
  58. </el-radio-group>
  59. </div>
  60. <div class="drawer-close" @click="closeDra('hand')"><i class="el-icon-close"></i></div>
  61. </div>
  62. <!-- 目标点 -->
  63. <div class="drawer" v-show="pointDrawer" style="width: 450px;">
  64. <div style="position: relative;">
  65. <div style="width: 100%;margin-bottom: 10px;">
  66. <!-- <el-tooltip class="item" effect="dark" content="将点位显示在地图上" placement="top">
  67. <el-button type="primary" icon="el-icon-search" size="mini" :disabled="multiple"></el-button>
  68. </el-tooltip> -->
  69. <el-tooltip class="item" effect="dark" content="上移" placement="top">
  70. <el-button type="primary" icon="el-icon-top" size="mini" :disabled="single" @click="moveUp"></el-button>
  71. </el-tooltip>
  72. <el-tooltip class="item" effect="dark" content="下移" placement="top">
  73. <el-button type="primary" icon="el-icon-bottom" size="mini" :disabled="single"
  74. @click="moveDown"></el-button>
  75. </el-tooltip>
  76. <el-popconfirm title="批量删除选中点位数据?" @confirm="removePoint">
  77. <el-button type="danger" icon="el-icon-delete" size="mini" :disabled="multiple" slot="reference"
  78. style="margin-left: 10px;"></el-button>
  79. </el-popconfirm>
  80. </div>
  81. <el-table ref="multipleTable" :data="pointList" tooltip-effect="dark" style="width: 100%" max-height="200px"
  82. @selection-change="handleSelectionChange" border>
  83. <el-table-column type="selection" width="45" align="center">
  84. </el-table-column>
  85. <el-table-column label="编号" width="60" show-overflow-tooltip align="center">
  86. <template slot-scope="scope">{{ scope.row.id }}</template>
  87. </el-table-column>
  88. <el-table-column label="x坐标" width="90" show-overflow-tooltip align="center">
  89. <template slot-scope="scope">{{ scope.row.x }}</template>
  90. </el-table-column>
  91. <el-table-column label="y坐标" width="90" show-overflow-tooltip align="center">
  92. <template slot-scope="scope">{{ scope.row.y }}</template>
  93. </el-table-column>
  94. <el-table-column label="操作" show-overflow-tooltip align="center">
  95. <template slot-scope="scope">
  96. <el-button size="mini" type="text" icon="el-icon-edit" @click="editPoint(scope.row)"
  97. style="margin-right: 10px;">编辑</el-button>
  98. <el-popconfirm title="删除当前点位数据?" @confirm="removePoint(scope.row)">
  99. <el-button size="mini" type="text" icon="el-icon-edit" slot="reference">删除</el-button>
  100. </el-popconfirm>
  101. </template>
  102. </el-table-column>
  103. </el-table>
  104. <div style="width: 100%;margin-top: 10px;">
  105. <el-button type="warning" icon="el-icon-caret-right" size="mini" :disabled="single">立即前往</el-button>
  106. <el-button type="success" icon="el-icon-folder-add" size="mini" :disabled="multiple"
  107. @click="taskGenerateDiaShow = true">生成任务</el-button>
  108. <el-button type="success" icon="el-icon-thumb" size="mini" @click="mapSelectEle('open')"
  109. v-if="!pointSelectionEnabled">地图选点模式</el-button>
  110. <el-button type="danger" icon="el-icon-thumb" size="mini" @click="mapSelectEle('close')"
  111. v-else>关闭选点模式</el-button>
  112. </div>
  113. </div>
  114. <div class="drawer-close" @click="closeDra('hand')"><i class="el-icon-close"></i></div>
  115. </div>
  116. <!-- 任务 -->
  117. <div class="drawer" v-if="taskDrawer" style="width: 300px;">
  118. <div style="position: relative;">
  119. <el-empty description="暂无创建的任务!" v-if="taskDataList.length < 1"></el-empty>
  120. <el-collapse v-else>
  121. <el-collapse-item v-for="(item, index) in taskDataList" :name="index" :key="item.taskId">
  122. <template slot="title"><span>任务名:{{ item.taskName }}</span>
  123. <el-tag type="info" v-if="item.status == 1" size="mini" class="task-status-tag">空闲中</el-tag><el-tag
  124. type="success" v-else size="mini" class="task-status-tag">执行中</el-tag>
  125. </template>
  126. <div class="collapse-content-div">
  127. <el-button type="danger" size="mini" icon="el-icon-delete"
  128. @click="removeTaskItem(item)">删除</el-button>
  129. <el-button type="warning" size="mini" icon="el-icon-view">查看</el-button>
  130. <el-button type="success" size="mini" icon="el-icon-caret-right" :disabled="item.status == 0"
  131. @click="executeTask(item)">执行</el-button>
  132. </div>
  133. </el-collapse-item>
  134. </el-collapse>
  135. </div>
  136. <div class="drawer-close" @click="closeDra('hand')" style="right: 1px;top: 1px;"><i class="el-icon-close"></i>
  137. </div>
  138. </div>
  139. </el-col>
  140. <el-col :xs="23" :sm="23" :md="23" :lg="23" :xl="23">
  141. <div class="main-content">
  142. <!-- 当前操作类型标记 -->
  143. <div class="hand-ment-mark">
  144. <el-tag type="danger" effect="dark" size="mini" v-if="nowHandMenu">{{ nowHandMenu }}</el-tag>
  145. </div>
  146. <OlMap ref="olmap" :width="olWidth + 'px'" :height="olHeight + 'px'" backgroundColor="#F5F5F5" :mapName="mapName"
  147. :pointSwitch="settingParams.pointId" :baseLayerShow="settingParams.baseMap"
  148. :pointSelectionEnabled="pointSelectionEnabled" :poseInitEnable="poseInitEnable" @addNowPoint="addNowPoint"
  149. :isRobotFollow="settingParams.follow" @initNavigationResult="initNavigationResult"></OlMap>
  150. </div>
  151. </el-col>
  152. </el-row>
  153. <el-dialog title="目标点编辑" :visible.sync="pointEditDiaShow" width="360px">
  154. <el-row>
  155. <span class="point-edit-span">x坐标(m)</span><el-input v-model="pointEditData.x" placeholder="请输入x坐标" size="mini"
  156. class="point-edit-input"></el-input>
  157. </el-row>
  158. <span class="point-edit-span">y坐标(m)</span><el-input v-model="pointEditData.y" placeholder="请输入y坐标"
  159. size="mini"></el-input>
  160. <span class="point-edit-span">规划类型</span><el-select v-model="pointEditData.type" placeholder="请选择" size="mini">
  161. <el-option v-for="item in planOptions" :key="item.value" :label="item.label" :value="item.value">
  162. </el-option>
  163. </el-select>
  164. <span class="point-edit-span">添加动作</span>
  165. <div v-for="(item, index) in pointEditData.actionMenuList" style="margin-bottom: 8px;" class="action-menu">
  166. <el-select v-model="item.value" placeholder="请选择" size="mini" @change="changeAction(index)">
  167. <el-option v-for="item in actionOptions" :key="item.value" :label="item.label" :value="item.value">
  168. </el-option>
  169. </el-select>
  170. <el-tooltip class="item" effect="dark" content="输入等待时间(秒)" placement="top">
  171. <el-input v-model="item.other" placeholder="时间(秒)" size="mini" style="width: 60px;margin-left: 5px;"
  172. class="action-menu_input" v-if="'other' in item"></el-input>
  173. </el-tooltip>
  174. <el-button type="info" icon="el-icon-plus" circle size="mini" style="margin-left: 5px;padding: 5px;"
  175. @click="appendActionMenu"></el-button>
  176. <el-button type="info" icon="el-icon-minus" circle size="mini" style="margin-left: 5px;padding: 5px;"
  177. @click="removeActionMenu(index)" v-if="index > 0"></el-button>
  178. </div>
  179. <span slot="footer" class="dialog-footer">
  180. <el-button @click="pointEditDiaShow = false">取 消</el-button>
  181. <el-button type="primary" @click="submitEditPoint">确 定</el-button>
  182. </span>
  183. </el-dialog>
  184. <el-dialog title="创建任务" :visible.sync="taskGenerateDiaShow" width="400px">
  185. <el-row>
  186. <span class="point-edit-span">任务名称</span><el-input v-model="generateTaskParam.taskName" placeholder="请输入任务名"
  187. size="mini" class="point-edit-input" style="width: 50%;"></el-input>
  188. <span class="point-edit-span">执行次数</span><el-input-number v-model="generateTaskParam.count"
  189. controls-position="right" :min="1" :max="100" size="mini" style="width: 50%;"></el-input-number>
  190. <span class="point-edit-span">开始时间</span><el-time-picker v-model="generateTaskParam.time" :picker-options="{
  191. selectableRange: '00:00:00 - 23:59:59'
  192. }" placeholder="选择时间" size="mini">
  193. </el-time-picker>
  194. <span class="point-edit-span">执行日期</span>
  195. <el-checkbox-group v-model="generateTaskParam.date" style="margin-bottom: 10px;">
  196. <el-checkbox label="1">周一</el-checkbox>
  197. <el-checkbox label="2">周二</el-checkbox>
  198. <el-checkbox label="3">周三</el-checkbox>
  199. <el-checkbox label="4">周四</el-checkbox>
  200. <el-checkbox label="5">周五</el-checkbox>
  201. <el-checkbox label="6">周六</el-checkbox>
  202. <el-checkbox label="7">周日</el-checkbox>
  203. </el-checkbox-group>
  204. </el-row>
  205. <span slot="footer" class="dialog-footer">
  206. <el-button @click="closeTaskGenerate()">取 消</el-button>
  207. <el-button type="primary" @click="submitTaskGenerate">确 定</el-button>
  208. </span>
  209. </el-dialog>
  210. <div class="info-dra-class-all">
  211. <el-drawer title="实时信息" :visible.sync="infoDrawer" :direction="'rtl'" :modal="false" :size="'100%'"
  212. :wrapperClosable="false" custom-class="navigation-info-dra-class" :modal-append-to-body="false">
  213. <div class="info-dra-class_content">
  214. <div style="margin-bottom: 20px;">
  215. <div class="info-dra_title">
  216. <div
  217. style="height: 20px;width: 5px;background-color: #6565FC;margin-right: 5px;border-radius: 4px 4px 0 0;">
  218. </div><span>当前地图</span>
  219. </div>
  220. <span class="info-dra_content">shanghai</span>
  221. </div>
  222. <div style="margin-bottom: 20px;">
  223. <div class="info-dra_title">
  224. <div
  225. style="height: 20px;width: 5px;background-color: #6565FC;margin-right: 5px;border-radius: 4px 4px 0 0;">
  226. </div><span>当前任务</span>
  227. </div>
  228. <span class="info-dra_content">测试任务</span>
  229. </div>
  230. <div style="margin-bottom: 20px;">
  231. <div class="info-dra_title">
  232. <div
  233. style="height: 20px;width: 5px;background-color: #6565FC;margin-right: 5px;border-radius: 4px 4px 0 0;">
  234. </div><span>实时信息</span>
  235. </div>
  236. <span class="info-dra_content info-dra_content_title">速度: <span
  237. class="info-dra_content_other">0.35m/s</span></span>
  238. <span class="info-dra_content info-dra_content_title">速度指令: <span
  239. class="info-dra_content_other">0.22m/s</span></span>
  240. <span class="info-dra_content info-dra_content_title">坐标: <span class="info-dra_content_other">(1.813,
  241. -63.931,
  242. 0.000)</span></span>
  243. <span class="info-dra_content info-dra_content_title">航向: <span
  244. class="info-dra_content_other">-79.6°</span></span>
  245. <span class="info-dra_content info-dra_content_title">累计里程: <span
  246. class="info-dra_content_other">5965352.00m</span></span>
  247. <span class="info-dra_content info-dra_content_title">配准误差: <span
  248. class="info-dra_content_other">10.000</span></span>
  249. <span class="info-dra_content info-dra_content_title">电量: <span
  250. class="info-dra_content_other">67%</span></span>
  251. </div>
  252. </div>
  253. </el-drawer>
  254. </div>
  255. <!-- 展开抽屉 -->
  256. <div class="fixed-right-center" @click="showInfoDra" v-if="!infoDrawer">
  257. <i class="el-icon-arrow-left"></i>
  258. </div>
  259. </div>
  260. </template>
  261. <script>
  262. import OlMap from "@/components/OlMap";
  263. export default {
  264. name: "Navigation",
  265. components: {
  266. OlMap
  267. },
  268. data() {
  269. return {
  270. activeIndex: -1, // 默认为没有激活的项
  271. settingDrawer: false,
  272. pointDrawer: false,
  273. taskDrawer: false,
  274. infoDrawer: true,
  275. pointEditDiaShow: false,
  276. taskGenerateDiaShow: false,
  277. // 是否开启地图选点
  278. pointSelectionEnabled: false,
  279. // 是否开启位置初始化功能
  280. poseInitEnable: false,
  281. // 功能设置参数
  282. settingParams: {
  283. pointCloud: false,
  284. baseMap: true,
  285. pointId: false,
  286. follow: false,
  287. network: false
  288. },
  289. // 非单个禁用
  290. single: true,
  291. // 非多个禁用
  292. multiple: true,
  293. taskDataList: [],
  294. // 目标点的编辑数据
  295. pointEditData: {
  296. id: '',
  297. x: '',
  298. y: '',
  299. type: '',
  300. // 添加动作菜单列表 (other:追加参数,例如原定等待选项的等待时间)
  301. actionMenuList: []
  302. },
  303. // 生成任务的参数
  304. generateTaskParam: {
  305. taskId: '',
  306. taskName: '',
  307. count: 1,
  308. time: '',
  309. date: [] // 1-7分别指代周一到周末
  310. },
  311. // 点位列表
  312. pointList: [],
  313. pointIds: [],
  314. // 路径类型
  315. planOptions: [
  316. { label: '自由路径', value: 0 },
  317. { label: '路网路径', value: 1 }
  318. ],
  319. // 动作类型
  320. actionOptions: [
  321. { label: '原地等待', value: 0 },
  322. { label: '开始录制', value: 1 },
  323. { label: '结束录制', value: 2 },
  324. { label: '添加建图轨迹', value: 3 },
  325. { label: '挂钩挂载', value: 4 },
  326. { label: '挂钩卸载', value: 5 }
  327. ],
  328. olWidth: 0, // 用于存储宽度的变量
  329. olHeight: 0,
  330. nowHandMenu: '',
  331. mapName: this.$route.params.mapName || '' // 地图名称
  332. };
  333. },
  334. created() {
  335. },
  336. mounted() {
  337. const mapId = this.$route.params.mapId;
  338. this.updateOlCss();
  339. window.addEventListener('resize', this.updateOlCss);
  340. },
  341. beforeDestroy() {
  342. window.removeEventListener('resize', this.updateOlCss);
  343. },
  344. methods: {
  345. updateOlCss() {
  346. const element = this.$el.querySelector('.main-content');
  347. this.olWidth = element.offsetWidth;
  348. this.olHeight = element.offsetHeight;
  349. },
  350. openDraSetting() {
  351. this.poseInitEnable = false;
  352. this.activeIndex = this.activeIndex == 0 ? -1 : 0;
  353. if (this.settingDrawer) {
  354. this.nowHandMenu = ''
  355. this.settingDrawer = false;
  356. return;
  357. }
  358. this.closeDra()
  359. this.nowHandMenu = '功能菜单操作'
  360. this.settingDrawer = true;
  361. },
  362. openPoint() {
  363. this.poseInitEnable = false
  364. this.activeIndex = this.activeIndex == 1 ? -1 : 1;
  365. if (this.pointDrawer) {
  366. this.pointDrawer = false;
  367. this.nowHandMenu = ''
  368. return;
  369. }
  370. this.closeDra()
  371. this.nowHandMenu = '目标点操作'
  372. this.pointDrawer = true;
  373. },
  374. openTask() {
  375. this.poseInitEnable = false
  376. this.activeIndex = this.activeIndex == 2 ? -1 : 2;
  377. if (this.taskDrawer) {
  378. this.taskDrawer = false;
  379. this.nowHandMenu = ''
  380. return;
  381. }
  382. this.closeDra()
  383. this.nowHandMenu = '任务操作'
  384. this.taskDrawer = true;
  385. },
  386. /**
  387. * 关闭左侧菜单的抽屉
  388. * type 类型(hand手动,auto自动)
  389. */
  390. closeDra(type) {
  391. this.settingDrawer = false;
  392. this.pointDrawer = false;
  393. this.taskDrawer = false;
  394. if (type == 'hand') {
  395. this.activeIndex = -1;
  396. }
  397. this.nowHandMenu = ''
  398. },
  399. handleSelectionChange(selection) {
  400. this.pointIds = selection.map(item => item.id)
  401. this.single = selection.length !== 1
  402. this.multiple = !selection.length
  403. },
  404. // 点位编辑
  405. editPoint(row) {
  406. this.pointEditDiaShow = true;
  407. this.pointEditData.id = row.id;
  408. this.pointEditData.x = row.x;
  409. this.pointEditData.y = row.y;
  410. this.pointEditData.type = row.type;
  411. this.pointEditData.actionMenuList = row.action
  412. },
  413. // 点位删除
  414. removePoint(row) {
  415. const idArr = [];
  416. const ids = row?.id || this.pointIds;
  417. if (ids) {
  418. idArr.push(...(Array.isArray(ids) ? ids : [ids]));
  419. idArr.forEach(id => {
  420. let indexToRemove = this.pointList.findIndex(item => item?.id === id);
  421. if (indexToRemove !== -1) {
  422. this.pointList.splice(indexToRemove, 1);
  423. if (this.pointList.length < 1) {
  424. // 重置地图的id计数器
  425. this.$refs.olmap.restIdNum();
  426. }
  427. this.$refs.olmap.removeIconHtmlById("pose-" + id);
  428. }
  429. });
  430. }
  431. },
  432. // 点位上移
  433. moveUp() {
  434. const index = this.pointList.findIndex(point => point.id == this.pointIds[0]);
  435. if (index !== -1 && index > 0) {
  436. let temp = this.pointList[index];
  437. this.$set(this.pointList, index, this.pointList[index - 1]);
  438. this.$set(this.pointList, index - 1, temp);
  439. }
  440. },
  441. // 点位下移
  442. moveDown() {
  443. const index = this.pointList.findIndex(point => point.id == this.pointIds[0]);
  444. if (index !== -1 && index < this.pointList.length - 1) {
  445. let temp = this.pointList[index];
  446. this.$set(this.pointList, index, this.pointList[index + 1]);
  447. this.$set(this.pointList, index + 1, temp);
  448. }
  449. },
  450. // 追加动作按钮
  451. appendActionMenu() {
  452. this.pointEditData.actionMenuList.push({ value: 0, other: 0 })
  453. },
  454. // 删除追加动作按钮
  455. removeActionMenu(index) {
  456. this.pointEditData.actionMenuList.splice(index, 1);
  457. },
  458. // 修改动作下拉值
  459. changeAction(index) {
  460. // 判断当前修改后是否是原定等待,如果不是则删除other属性
  461. let item = this.pointEditData.actionMenuList[index];
  462. if (item && 'other' in item) {
  463. delete item.other; // 删除 'other' 属性
  464. } else {
  465. item.other = 0;
  466. }
  467. },
  468. clearActionDia() {
  469. this.pointEditData.id = '';
  470. this.pointEditData.x = '';
  471. this.pointEditData.y = '';
  472. this.pointEditData.type = '';
  473. this.pointEditData.actionMenuList = [];
  474. },
  475. // 提交点位修改
  476. submitEditPoint() {
  477. this.pointEditDiaShow = false;
  478. // 模拟数据修改
  479. const point = this.pointList.find(item => item.id === this.pointEditData.id);
  480. if (this.pointEditData.actionMenuList)
  481. if (point) {
  482. // 找到对应元素,更新数据(真实情况下发请求修改,然后重新查询点位列表)
  483. point.x = this.pointEditData.x;
  484. point.y = this.pointEditData.y;
  485. point.type = this.pointEditData.type;
  486. point.action = this.pointEditData.actionMenuList;
  487. this.$modal.msgSuccess("当前点位数据已修改");
  488. }
  489. },
  490. // 生成任务
  491. submitTaskGenerate() {
  492. // 查询当前选择的id对应的点位对象数据
  493. const orderedPoints = this.pointIds.map(id => this.pointList.find(point => point.id === id));
  494. if (!this.generateTaskParam.taskName || !this.generateTaskParam.count || !this.generateTaskParam.time || this.generateTaskParam.date.length < 1) {
  495. this.$message({
  496. message: '请完善任务数据!',
  497. type: 'warning'
  498. });
  499. return;
  500. }
  501. this.generateTaskParam.taskId = Math.floor(Math.random() * 10001);
  502. let taskData = {
  503. taskId: this.generateTaskParam.taskId,
  504. taskName: this.generateTaskParam.taskName,
  505. count: this.generateTaskParam.count,
  506. time: this.generateTaskParam.time,
  507. date: this.generateTaskParam.date,
  508. status: 1,
  509. points: orderedPoints
  510. }
  511. // 实际使用需要提交任务后等待后端添加完毕然后查询列表,这里临时用push
  512. this.taskDataList.push(taskData)
  513. this.restGenerateParam();
  514. this.taskGenerateDiaShow = false;
  515. this.pointIds = [];
  516. this.$modal.msgSuccess("点位任务创建成功");
  517. },
  518. // 初始化导航
  519. initNavigation() {
  520. this.closeDra()
  521. if (this.poseInitEnable) {
  522. this.poseInitEnable = false;
  523. this.nowHandMenu = ''
  524. } else {
  525. this.poseInitEnable = true;
  526. this.nowHandMenu = '初始化导航'
  527. }
  528. this.pointSelectionEnabled = false;
  529. this.activeIndex = this.activeIndex == 3 ? -1 : 3;
  530. },
  531. // 重启导航
  532. restNavigation() {
  533. this.$confirm('将重启当前导航, 是否继续?', '提示', {
  534. confirmButtonText: '确定',
  535. cancelButtonText: '取消',
  536. customClass: 'el-message-box-cust',
  537. type: 'warning'
  538. }).then(() => {
  539. this.$message({
  540. type: 'success',
  541. message: '导航已重启!'
  542. });
  543. }).catch(() => { });
  544. },
  545. // 关闭导航
  546. offNavigation() {
  547. this.$confirm('将关闭当前导航, 是否继续?', '提示', {
  548. confirmButtonText: '确定',
  549. cancelButtonText: '取消',
  550. customClass: 'el-message-box-cust',
  551. type: 'warning'
  552. }).then(() => {
  553. this.$message({
  554. type: 'success',
  555. message: '导航已关闭!'
  556. });
  557. }).catch(() => { });
  558. },
  559. // 关闭任务生成弹窗
  560. closeTaskGenerate() {
  561. this.taskGenerateDiaShow = false;
  562. this.restGenerateParam();
  563. },
  564. // 重置任务创建弹窗数据
  565. restGenerateParam() {
  566. this.generateTaskParam = {
  567. taskId: '',
  568. taskName: '',
  569. number: 1,
  570. time: '',
  571. date: [] // 1-7分别指代周一到周末
  572. }
  573. },
  574. // 任务删除
  575. removeTaskItem(data) {
  576. this.$confirm('删除名为' + data.taskName + '的任务', '删除', {
  577. confirmButtonText: '确定',
  578. cancelButtonText: '取消',
  579. customClass: 'el-message-box-cust',
  580. type: 'warning'
  581. }).then(() => {
  582. this.$message({
  583. type: 'success',
  584. message: '已删除!'
  585. });
  586. this.taskDataList = this.taskDataList.filter(task => task.taskId !== data.taskId);
  587. }).catch(() => { });
  588. },
  589. // 执行任务
  590. executeTask(data) {
  591. this.$confirm('开始执行任务' + data.taskName + '?', '执行', {
  592. confirmButtonText: '确定',
  593. cancelButtonText: '取消',
  594. customClass: 'el-message-box-cust',
  595. type: 'warning'
  596. }).then(() => {
  597. this.$message({
  598. type: 'success',
  599. message: '任务已开始执行!'
  600. });
  601. this.taskDataList.forEach(task => {
  602. if (task.taskId === data.taskId) {
  603. task.status = 0;
  604. }
  605. });
  606. }).catch(() => { });
  607. },
  608. // 展开右侧实时信息
  609. showInfoDra() {
  610. this.infoDrawer = true;
  611. },
  612. test() {
  613. console.log(this.set);
  614. },
  615. // 开启地图选点
  616. mapSelectEle(type) {
  617. if (type == 'open') {
  618. this.pointSelectionEnabled = true;
  619. this.poseInitEnable = false;
  620. this.$notify({
  621. title: '地图选择',
  622. message: '已开启选择模式',
  623. type: 'success',
  624. duration: 1000
  625. });
  626. } else {
  627. this.pointSelectionEnabled = false;
  628. this.$notify.info({
  629. title: '关闭选择',
  630. message: '已关闭选择模式',
  631. duration: 1000
  632. });
  633. }
  634. },
  635. // 将当前选择的点位数据添加到点位列表中
  636. // currentCoordinate 坐标信息 currentPlace 画布位置信息
  637. addNowPoint(currentCoordinate, currentPlace) {
  638. let coordData = {
  639. id: currentCoordinate[0],
  640. x: currentCoordinate[1].toFixed(3),
  641. y: currentCoordinate[2].toFixed(3),
  642. placeX: currentPlace[0].toFixed(3),
  643. placeY: currentPlace[1].toFixed(3),
  644. type: 0,
  645. action: [{ value: 0, other: 0 }]
  646. }
  647. this.pointList.push(coordData);
  648. },
  649. /**
  650. * 位姿初始化操作绘制的回执
  651. * @param position 坐标
  652. * @param angle 角度
  653. */
  654. initNavigationResult(position, angle) {
  655. console.log(position);
  656. console.log(angle);
  657. }
  658. }
  659. };
  660. </script>
  661. <style scoped>
  662. .point-edit-span {
  663. display: block;
  664. margin: 10px 0;
  665. font-weight: bold;
  666. }
  667. .drawer {
  668. height: 100%;
  669. position: absolute;
  670. top: 0;
  671. left: 100%;
  672. /* box-shadow: 4px 4px 12px rgba(201, 201, 201, 0.2); */
  673. /* 右边和下边的阴影 */
  674. border-radius: 0 0 12px 0;
  675. border-left: 1px solid #F0F0F0;
  676. padding: 8px 15px;
  677. border-right: 1px solid #ececec;
  678. border-bottom: 1px solid #ececec;
  679. overflow-y: auto;
  680. background-color: #fff;
  681. z-index: 1000;
  682. }
  683. .drawer-close {
  684. position: absolute;
  685. right: 3px;
  686. top: 3px;
  687. cursor: pointer;
  688. }
  689. .drawer-title {
  690. position: absolute;
  691. top: -23px;
  692. left: -8px;
  693. font-size: 13px;
  694. font-weight: bold;
  695. color: #838383;
  696. }
  697. .drawer p {
  698. font-size: 13px;
  699. border-left: 5px #D1D1D1 solid;
  700. padding-left: 5px;
  701. margin: 8px 0;
  702. border-radius: 3px 0 0 3px;
  703. }
  704. .img-container {
  705. text-align: center;
  706. display: flex;
  707. flex-direction: column;
  708. align-items: center;
  709. justify-content: center;
  710. /* 垂直居中子元素 */
  711. border-radius: 7px;
  712. background: linear-gradient(135deg, #00bcd4, #009688);
  713. cursor: pointer;
  714. width: 70%;
  715. aspect-ratio: 1;
  716. /* 设置宽高比为1,即高度和宽度相等 */
  717. margin-top: 10px;
  718. }
  719. .img-container:hover {
  720. transform: scale(1.02);
  721. /* 鼠标悬停时放大 */
  722. box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1);
  723. /* 增加阴影效果 */
  724. background-color: #00796b;
  725. /* 改变背景颜色 */
  726. }
  727. .img-container:active {
  728. transform: scale(0.98);
  729. /* 点击时缩小 */
  730. box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
  731. /* 点击时加深阴影 */
  732. background-color: #004d40;
  733. /* 点击时改变背景颜色 */
  734. filter: brightness(1.1);
  735. /* 点击时稍微增加亮度 */
  736. }
  737. .img-container img {
  738. opacity: 1;
  739. }
  740. .img-container span {
  741. font-size: 12px;
  742. color: #ffffff;
  743. font-weight: bold;
  744. }
  745. /* 激活时的样式 */
  746. .img-container.active {
  747. background: linear-gradient(135deg, #007d8d, #004b43);
  748. }
  749. .explore-unit {
  750. margin-left: 8px;
  751. }
  752. ::v-deep .el-dialog__body {
  753. padding: 20px 20px 0 20px;
  754. }
  755. ::v-deep .download-map .el-dialog__body {
  756. padding: 10px 20px 0 20px !important;
  757. }
  758. ::v-deep .el-table--medium .el-table__cell {
  759. padding: 6px 0;
  760. }
  761. ::v-deep .action-menu .action-menu_input .el-input__inner {
  762. padding: 0 5px;
  763. }
  764. .task-status-tag {
  765. margin-left: 20px;
  766. }
  767. ::v-deep .drawer .el-collapse-item__header {
  768. height: 38px;
  769. line-height: 38px;
  770. color: #767676;
  771. font-weight: bold;
  772. }
  773. ::v-deep .drawer .el-collapse-item__content {
  774. text-align: left;
  775. padding-bottom: 10px;
  776. }
  777. ::v-deep .drawer .el-collapse {
  778. border: 1px solid #EBEEF5;
  779. padding: 0 8px;
  780. border-radius: 5px;
  781. }
  782. .collapse-content-div {
  783. margin-top: 0;
  784. }
  785. ::v-deep .collapse-content-div .el-button--mini {
  786. padding: 4px 10px;
  787. }
  788. .fixed-right-center {
  789. position: fixed;
  790. top: 50%;
  791. right: 0;
  792. transform: translateY(-50%);
  793. background-color: rgba(0, 0, 255, 0.6);
  794. color: white;
  795. border-radius: 6px 0 0 6px;
  796. cursor: pointer;
  797. }
  798. .info-dra-class_content {
  799. padding: 0 20px 20px 20px;
  800. }
  801. .info-dra_title {
  802. display: flex;
  803. /* 启用 Flexbox 布局 */
  804. justify-content: flex-start;
  805. /* 水平从左排列 */
  806. align-items: center;
  807. color: #8a8a8a;
  808. font-size: 15px;
  809. font-weight: bold;
  810. border-bottom: 2px solid #B9B9FF;
  811. margin-bottom: 10px;
  812. }
  813. .info-dra_content {
  814. color: #5A5A5A;
  815. font-size: 14px;
  816. margin-left: 8px;
  817. display: block;
  818. margin-bottom: 8px;
  819. }
  820. .info-dra_content_title {
  821. font-weight: bold;
  822. }
  823. .info-dra_content_other {
  824. font-weight: 400;
  825. }
  826. .hand-ment-mark {
  827. position: absolute;
  828. bottom: 12px;
  829. left: 12px;
  830. z-index: 1000;
  831. }
  832. ::v-deep .info-dra-class-all .el-drawer__wrapper {
  833. width: 15%;
  834. left: 85%;
  835. }
  836. @media (max-width: 1599px) {
  837. ::v-deep .info-dra-class-all .el-drawer__wrapper {
  838. width: 18%;
  839. left: 82%;
  840. }
  841. }
  842. @media (max-width: 1269px) {
  843. ::v-deep .info-dra-class-all .el-drawer__wrapper {
  844. width: 21%;
  845. left: 79%;
  846. }
  847. }
  848. @media (max-width: 1000px) {
  849. ::v-deep .info-dra-class-all .el-drawer__wrapper {
  850. width: 24%;
  851. left: 76%;
  852. }
  853. }
  854. .notification__title {
  855. font-size: 1.2rem;
  856. /* 默认字体大小 */
  857. }
  858. .main-content {
  859. width: 100%;
  860. min-height: calc(100vh - 84px);
  861. overflow: hidden;
  862. position: relative;
  863. }
  864. .main {
  865. width: 100%;
  866. min-height: calc(100vh - 84px);
  867. min-width: 1500px;
  868. overflow-x: auto;
  869. }
  870. .main-menu {
  871. display: flex;
  872. flex-direction: column;
  873. justify-content: center;
  874. align-items: center;
  875. }
  876. </style>
  877. <style>
  878. .navigation-info-dra-class {
  879. background-color: #ffffff;
  880. box-shadow: none;
  881. border-radius: 5px 0 0 5px;
  882. }
  883. .navigation-info-dra-class .el-drawer__header {
  884. margin-bottom: 20px;
  885. }
  886. </style>