index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. <template>
  2. <div class="main">
  3. <div class="main-head">
  4. <el-button type="primary" @click="onAddGroup">新增分组</el-button>
  5. </div>
  6. <div class="main-content">
  7. <template v-for="item in group">
  8. <el-card>
  9. <el-button type="primary" @click="onAddKey(item)">新增KEY</el-button>
  10. <template v-if="item.keyList?.length > 0">
  11. <el-button v-if="!item.isStart" type="success" @click="onStartKey(item)">开始</el-button>
  12. <el-button v-else type="danger" @click="onStopKey(item)">暂停</el-button>
  13. <el-button v-if="!item.isStart" type="warning" @click="onEditGroup(item)">编辑分组</el-button>
  14. <el-button v-if="!item.isStart" type="danger" @click="onDelGroup(item)">删除分组</el-button>
  15. </template>
  16. <div>{{item.name}}({{item.second}}秒)</div>
  17. <div>{{item.cql}}</div>
  18. <el-divider />
  19. <div>
  20. <template v-for="(key, keyIndex) in item.keyList">
  21. <div :style="`color: ${key.online ? '' : 'red'}`">
  22. {{keyIndex + 1}}、{{key.key}}<el-button v-if="!item.isStart" type="danger" size="small" @click="onDelKey(item, key)">删除</el-button>
  23. <template v-if="item.isStart">
  24. <div class="key-content">
  25. <div class="key-position">
  26. <EasyMapComponent
  27. v-if="key.online"
  28. class="map"
  29. @easyMapLoad="(map, func) => initKeyMap(map, key)"
  30. />
  31. <div v-else>无信号</div>
  32. </div>
  33. <div class="key-heart">
  34. <HeartLineChart :data="key.apiData"/>
  35. </div>
  36. </div>
  37. </template>
  38. </div>
  39. </template>
  40. </div>
  41. </el-card>
  42. </template>
  43. </div>
  44. <CusDialog
  45. title="新增分组"
  46. v-model:show="showGroupDialog"
  47. @submit="onSaveGroup"
  48. height="auto"
  49. >
  50. <div style="padding: 20px;">
  51. <CusForm ref="ref_groupForm" @handleEnter="onSaveGroup">
  52. <CusFormColumn
  53. label="分组名称"
  54. required
  55. :span="24"
  56. v-model:param="groupForm.name"
  57. />
  58. <CusFormColumn
  59. label="心跳频率"
  60. required
  61. link="number"
  62. unit="秒"
  63. :span="24"
  64. v-model:param="groupForm.second"
  65. />
  66. <CusFormColumn
  67. label="cql——{KEY}"
  68. required
  69. type="textarea"
  70. :span="24"
  71. :rows="8"
  72. v-model:param="groupForm.cql"
  73. />
  74. </CusForm>
  75. </div>
  76. </CusDialog>
  77. <CusDialog
  78. title="新增KEY"
  79. v-model:show="showKeyDialog"
  80. @submit="onSaveKey"
  81. height="auto"
  82. >
  83. <div style="padding: 20px;">
  84. <CusForm ref="ref_keyForm" @handleEnter="onSaveKey">
  85. <CusFormColumn
  86. label="KEY"
  87. required
  88. :span="24"
  89. v-model:param="keyForm.key"
  90. />
  91. </CusForm>
  92. </div>
  93. </CusDialog>
  94. </div>
  95. </template>
  96. <script lang="ts">
  97. import {
  98. defineComponent,
  99. computed,
  100. onMounted,
  101. ref,
  102. reactive,
  103. watch,
  104. getCurrentInstance,
  105. ComponentInternalInstance,
  106. toRefs,
  107. nextTick
  108. } from 'vue'
  109. import {useStore} from 'vuex'
  110. import {useRouter, useRoute} from 'vue-router'
  111. import {ElMessage, ElMessageBox} from "element-plus";
  112. import axios from "axios";
  113. import * as style from 'ol/style'
  114. import HeartLineChart from './heart-line.vue'
  115. export default defineComponent({
  116. name: '',
  117. components: {
  118. HeartLineChart
  119. },
  120. props: {},
  121. setup(props, {emit}) {
  122. const store = useStore();
  123. const router = useRouter();
  124. const route = useRoute();
  125. const that = (getCurrentInstance() as ComponentInternalInstance).appContext.config.globalProperties
  126. const state = reactive({
  127. DB: <any>null,
  128. ObjectStore: 'track-status',
  129. group: <any>[],
  130. showGroupDialog: false,
  131. groupForm: {},
  132. showKeyDialog: false,
  133. keyForm: {},
  134. })
  135. const ref_groupForm = ref()
  136. const ref_keyForm = ref()
  137. const request = window.indexedDB.open('SeatTools', 1)
  138. request.onerror = function (event) {}
  139. request.onsuccess = function (event) {
  140. state.DB = request.result
  141. state.group = []
  142. init()
  143. }
  144. request.onupgradeneeded = function (event: any) {
  145. state.DB = event.target.result
  146. if (!state.DB.objectStoreNames.contains(state.ObjectStore)) {
  147. const objectStore = state.DB.createObjectStore(state.ObjectStore, { autoIncrement: true })
  148. }
  149. }
  150. const init = () => {
  151. const os = state.DB.transaction(state.ObjectStore).objectStore(state.ObjectStore)
  152. os.openCursor().onsuccess = e => {
  153. const cursor = e.target.result
  154. if (cursor) {
  155. if (state.group.every(v => v.id !== cursor.key)) {
  156. state.group.push({
  157. id: cursor.key,
  158. name: cursor.value.name,
  159. cql: cursor.value.cql,
  160. second: cursor.value.second,
  161. keyList: JSON.parse(cursor.value.keyList),
  162. isStart: false
  163. })
  164. }
  165. cursor.continue()
  166. } else {
  167. }
  168. }
  169. }
  170. const onAddGroup = () => {
  171. state.showGroupDialog = true
  172. state.groupForm = {}
  173. }
  174. const onSaveGroup = () => {
  175. ref_groupForm.value.submit().then(() => {
  176. if (!state.groupForm.id) {
  177. const obj = {
  178. name: state.groupForm.name,
  179. second: state.groupForm.second,
  180. cql: state.groupForm.cql,
  181. keyList: JSON.stringify([])
  182. }
  183. const re = state.DB.transaction([state.ObjectStore], 'readwrite').objectStore(state.ObjectStore).add(obj)
  184. re.onsuccess = e => {
  185. ElMessage.success('添加成功!')
  186. state.showGroupDialog = false
  187. init()
  188. }
  189. re.onerror = e => {
  190. ElMessage.error('添加失败!')
  191. }
  192. } else {
  193. const obj = {
  194. name: state.groupForm.name,
  195. second: state.groupForm.second,
  196. cql: state.groupForm.cql,
  197. keyList: JSON.stringify(state.groupForm.keyList.map(v => {
  198. return {
  199. key: v.key
  200. }
  201. }))
  202. }
  203. const re = state.DB.transaction([state.ObjectStore], 'readwrite').objectStore(state.ObjectStore).put(obj, state.groupForm.id)
  204. re.onsuccess = e => {
  205. ElMessage.success('更新成功!')
  206. state.group.forEach(v => {
  207. if (v.id === state.groupForm.id) {
  208. v = state.groupForm
  209. }
  210. })
  211. state.showGroupDialog = false
  212. }
  213. re.onerror = e => {
  214. ElMessage.error('更新失败!')
  215. }
  216. }
  217. })
  218. }
  219. const onAddKey = (group) => {
  220. state.keyForm = {
  221. group: group
  222. }
  223. state.showKeyDialog = true
  224. }
  225. const onSaveKey = () => {
  226. ref_keyForm.value.submit().then(() => {
  227. const kList = [...state.keyForm.group.keyList.map(v => {
  228. const o = {key: v.key}
  229. return o
  230. }), {key: state.keyForm.key}]
  231. const obj = {
  232. name: state.keyForm.group.name,
  233. second: state.keyForm.group.second,
  234. cql: state.keyForm.group.cql,
  235. keyList: JSON.stringify(kList)
  236. }
  237. const re = state.DB.transaction([state.ObjectStore], 'readwrite').objectStore(state.ObjectStore).put(obj, state.keyForm.group.id)
  238. re.onsuccess = e => {
  239. ElMessage.success('更新成功!')
  240. state.group.forEach(v => {
  241. if (v.id === state.keyForm.group.id) {
  242. v.keyList = JSON.parse(JSON.stringify(kList))
  243. }
  244. })
  245. state.showKeyDialog = false
  246. }
  247. re.onerror = e => {
  248. ElMessage.error('更新失败!')
  249. }
  250. })
  251. }
  252. const onStartKey = (group) => {
  253. group.isStart = true
  254. const handle = () => {
  255. group.keyList.forEach(v => {
  256. let url = `/${store.state.app.apiProxy.rhFindShipApi}/geomesa/queryFusionShip/?cql=`;
  257. url += encodeURIComponent(group.cql.split('{KEY}').join(v.key))
  258. axios.get(url).then(res => {
  259. if (res.data.data?.length > 0) {
  260. v.online = true
  261. if (v.apiData) {
  262. v.apiData = [...v.apiData, res.data.data[0]]
  263. } else {
  264. v.apiData = [res.data.data[0]]
  265. }
  266. setKeyMap(v, v.apiData[v.apiData.length - 1])
  267. } else {
  268. v.online = false
  269. if (v.apiData) {
  270. v.apiData = [...v.apiData, {}]
  271. } else {
  272. v.apiData = [{}]
  273. }
  274. }
  275. })
  276. })
  277. }
  278. handle()
  279. group.interval = setInterval(() => {
  280. handle()
  281. }, 1000 * group.second)
  282. }
  283. const onStopKey = (group) => {
  284. group.isStart = false
  285. clearInterval(group.interval)
  286. group.interval = null
  287. group.keyList?.forEach(v => {
  288. v.apiData = []
  289. })
  290. }
  291. const setKeyMap = (key, data) => {
  292. if (key.MAP) {
  293. that.$easyMap.initShape({
  294. map: key.MAP,
  295. layerName: "MAP",
  296. layerZIndex: 9,
  297. list: [
  298. {
  299. easyMapParams: {
  300. id: new Date().getTime(),
  301. position: data.location,
  302. normalStyle: [
  303. new style.Style({
  304. image: new style.Circle({
  305. radius: 5,
  306. fill: new style.Fill({
  307. color: 'red',
  308. }),
  309. }),
  310. })
  311. ]
  312. }
  313. }
  314. ]
  315. });
  316. key.MAP.getView().animate({
  317. center: that.$easyMap.formatPosition.wptTcpt(data.location)
  318. })
  319. }
  320. }
  321. const initKeyMap = (map, key) => {
  322. key.MAP = map
  323. if (key.apiData?.length > 0) {
  324. const data = key.apiData[key.apiData.length - 1]
  325. setKeyMap(key, data)
  326. }
  327. }
  328. const onDelGroup = (group) => {
  329. ElMessageBox.confirm(`是否删除分组:${group.name}`, "提示", {
  330. confirmButtonText: "确定",
  331. cancelButtonText: "取消",
  332. type: "warning",
  333. }).then(() => {
  334. const re = state.DB.transaction([state.ObjectStore], 'readwrite').objectStore(state.ObjectStore).delete(group.id)
  335. re.onsuccess = e => {
  336. ElMessage.success('删除成功!')
  337. state.group.forEach((v, i) => {
  338. if (v.id === group.id) {
  339. state.group.splice(i, 1)
  340. }
  341. })
  342. }
  343. re.onerror = e => {
  344. ElMessage.error('更新失败!')
  345. }
  346. })
  347. }
  348. const onEditGroup = (group) => {
  349. console.log(group)
  350. state.groupForm = group
  351. state.showGroupDialog = true
  352. }
  353. const onDelKey = (group, key) => {
  354. ElMessageBox.confirm(`是否删除KEY:${key.key}`, "提示", {
  355. confirmButtonText: "确定",
  356. cancelButtonText: "取消",
  357. type: "warning",
  358. }).then(() => {
  359. group.keyList.forEach((v, i) => {
  360. if (v.key === key.key) {
  361. group.keyList.splice(i, 1)
  362. }
  363. })
  364. const obj = {
  365. name: group.name,
  366. second: group.second,
  367. cql: group.cql,
  368. keyList: JSON.stringify(group.keyList.map(v => {
  369. return {key: v.key}
  370. }))
  371. }
  372. const re = state.DB.transaction([state.ObjectStore], 'readwrite').objectStore(state.ObjectStore).put(obj, group.id)
  373. re.onsuccess = e => {
  374. ElMessage.success('更新成功!')
  375. }
  376. re.onerror = e => {
  377. ElMessage.error('更新失败!')
  378. }
  379. })
  380. }
  381. onMounted(() => {
  382. })
  383. return {
  384. ...toRefs(state),
  385. ref_groupForm,
  386. ref_keyForm,
  387. onAddGroup,
  388. onSaveGroup,
  389. onAddKey,
  390. onSaveKey,
  391. onStartKey,
  392. onStopKey,
  393. initKeyMap,
  394. onEditGroup,
  395. onDelGroup,
  396. onDelKey
  397. }
  398. },
  399. })
  400. </script>
  401. <style scoped lang="scss">
  402. .main {
  403. width: 100%;
  404. height: 100vh;
  405. display: flex;
  406. flex-direction: column;
  407. .main-head {
  408. }
  409. .main-content {
  410. flex: 1;
  411. overflow: auto;
  412. .key-content {
  413. width: 100%;
  414. height: 140px;
  415. display: flex;
  416. .key-position {
  417. width: 200px;
  418. height: 100%;
  419. :deep(.easy-map-ol) {
  420. .easy-map_ol-default-mouse-position, .easy-map_ol-default-zoom, .easy-map_ol-default-scaleLine {
  421. display: none;
  422. }
  423. }
  424. }
  425. .key-heart {
  426. flex: 1;
  427. }
  428. }
  429. }
  430. }
  431. </style>