BottomMenus.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. <template>
  2. <div id="bottomMenus">
  3. <!-- 底部菜单动态SVG底座 -->
  4. <BottomMenuSvg id="svgBox" @changeShowBottomMenusStatus="changeShowBottomMenusStatus()" />
  5. <!-- 申请任务弹窗 -->
  6. <CreateTaskForm @changeShowBottomMenusStatus="changeShowBottomMenusStatus" />
  7. <!-- 我的任务弹窗 -->
  8. <MyMission @changeShowBottomMenusStatus="changeShowBottomMenusStatus" />
  9. <!-- 同屏对比弹窗 -->
  10. <SameScreenComparison @changeShowBottomMenusStatus="changeShowBottomMenusStatus" />
  11. <!-- 上传数据弹窗 -->
  12. <UploadingData @changeShowBottomMenusStatus="changeShowBottomMenusStatus" />
  13. <!-- 报告输出弹窗 -->
  14. <ReportOutput @changeShowBottomMenusStatus="changeShowBottomMenusStatus" />
  15. <!-- 自定义模型 -->
  16. <CustomModelDialog />
  17. <!-- 底部菜单主体 -->
  18. <div
  19. id="menusBox"
  20. :style="{
  21. width: showBottomMenusStatus ? '981px' : '0px',
  22. height: showBottomMenusStatus ? '200px' : '0px',
  23. border: showBottomMenusStatus ? '1px solid #00aaff' : 'none'
  24. }"
  25. >
  26. <!-- 模块遍历渲染也是menus对象的第一层数组 -->
  27. <div
  28. class="bottomMenus_box"
  29. v-for="(item, index) in menus"
  30. :key="index"
  31. :style="{ width: item.width ? item.width : 'auto' }"
  32. >
  33. <!-- 模块标题 -->
  34. <div class="bottomMenus_box_title">{{ item.title }}</div>
  35. <!-- 模块下的菜单主体 -->
  36. <div class="bottomMenus_box_main">
  37. <!-- 遍历渲染每个模块下的子菜单,也是menus数组中subMenu数组 -->
  38. <div
  39. class="colBtuMenu"
  40. @click="changeBottomMenu(item.index, subItem.index, subItem.clickEmit)"
  41. v-for="(subItem, subIndex) in item.subMenu"
  42. :key="subIndex"
  43. >
  44. <!-- 选中状态的背景高亮(舍弃) -->
  45. <div :class="ifMenuIndex(item.index, subItem.index) ? 'colBtuMenuShadow' : ''"></div>
  46. <!-- 子菜单图标的选择性渲染 -->
  47. <el-image class="BtuMenu_hover" :src="returnBgImage(subItem.bgImage + '-a')"></el-image>
  48. <el-image class="BtuMenu" :src="returnBgImage(subItem.bgImage)"></el-image>
  49. <!-- 子菜单标题 -->
  50. <div class="BtuMenu_title">
  51. {{ subItem.title }}
  52. </div>
  53. </div>
  54. </div>
  55. </div>
  56. </div>
  57. </div>
  58. </template>
  59. <script>
  60. /**
  61. * 底部菜单组件
  62. * @author: LiuMengxiang
  63. * @Date: 2022年11月14-18日
  64. */
  65. import BottomMenuSvg from "./BottomMenuSvg.vue";
  66. import CreateTaskForm from "./BottomForm/CreateTaskForm.vue";
  67. import MyMission from "./BottomForm/MyMission.vue";
  68. import SameScreenComparison from "./BottomForm/SameScreenComparison.vue";
  69. import UploadingData from "./BottomForm/UploadingData.vue";
  70. import CustomModelDialog from "./BottomForm/CustomModelDialog.vue";
  71. import ReportOutput from "./BottomForm/ReportOutput.vue";
  72. export default {
  73. name: "BottomMenus",
  74. components: {
  75. BottomMenuSvg,
  76. CreateTaskForm,
  77. MyMission,
  78. SameScreenComparison,
  79. UploadingData,
  80. CustomModelDialog,
  81. ReportOutput
  82. },
  83. data() {
  84. return {
  85. // 弹窗打开状态
  86. dialogVisibleStatus: false,
  87. // 菜单主体显示状态(默认false)
  88. showBottomMenusStatus: false,
  89. // 底部菜单对象
  90. menus: [
  91. {
  92. index: 0,
  93. width: "164px",
  94. title: "任务申请",
  95. subMenu: [
  96. { index: 0, title: "申请任务", bgImage: "sqrw", clickEmit: "sqrw" },
  97. { index: 1, title: "我的任务", bgImage: "wdrw", clickEmit: "wdrw" }
  98. ]
  99. },
  100. {
  101. index: 1,
  102. width: "509px",
  103. title: "疑点分析",
  104. subMenu: [
  105. {
  106. index: 0,
  107. title: "疑点审计",
  108. bgImage: "ydsj",
  109. clickEmit: "caseAuditEvent"
  110. },
  111. {
  112. index: 1,
  113. title: "标记疑点",
  114. bgImage: "bjyd",
  115. clickEmit: "labelCaseEvent"
  116. },
  117. { index: 2, title: "同屏对比", bgImage: "tpdb", clickEmit: "tpdb" },
  118. {
  119. index: 3,
  120. title: "卷帘对比",
  121. bgImage: "jldb",
  122. clickEmit: "JLControl"
  123. },
  124. { index: 4, title: "上传数据", bgImage: "scsj", clickEmit: "scsj" },
  125. {
  126. index: 5,
  127. title: "自定义模型",
  128. bgImage: "zdymx",
  129. clickEmit: "customModelEvent"
  130. }
  131. ]
  132. },
  133. {
  134. index: 2,
  135. width: "94px",
  136. title: "疑点报告",
  137. subMenu: [{ index: 0, title: "报告输出", bgImage: "bgsc", clickEmit: "ReportOutput" }]
  138. },
  139. {
  140. index: 3,
  141. width: "94px",
  142. title: "现场勘查",
  143. subMenu: [{ index: 0, title: "发到手机", bgImage: "fdsj", clickEmit: "notFound" }]
  144. }
  145. ]
  146. };
  147. },
  148. mounted() {
  149. // 报告输出事件监听
  150. this.$bus.$on("notFound", () => {
  151. this.$message.info("页面开发中,敬请期待!");
  152. });
  153. },
  154. destroy() {
  155. // 当容器销毁时,需要停止监听该事件
  156. this.$bus.$off("notFound");
  157. },
  158. props: [],
  159. methods: {
  160. // 根据菜单父级index和子菜单index,判断全局变量已选中底部菜单的index对比,返回状态。
  161. ifMenuIndex(index, subIndex) {
  162. if (index == 1) {
  163. if (subIndex === 0 || subIndex === 1 || subIndex === 3) {
  164. return this.$store.state.bottomMenuIndexs.index == index && this.$store.state.bottomMenuIndexs.subIndex == subIndex;
  165. }
  166. }
  167. },
  168. // 根据菜单父级index和子菜单index,更新全局变量。
  169. changeBottomMenu(index, subIndex, clickEvent) {
  170. // 该逻辑可能会舍弃
  171. this.$store.commit("changeBottomMenu", {
  172. index: index,
  173. subIndex: subIndex
  174. });
  175. if (clickEvent) {
  176. // 调用全局事件总线中的指定事件
  177. this.$bus.$emit(clickEvent);
  178. }
  179. },
  180. // 根据菜单参数bgImage,菜单父级index和子菜单index,判断全局变量已选中底部菜单的index对比,返回不同状态下的icon图标地址。
  181. returnBgImage(bgImage, index, subIndex) {
  182. if (this.$store.state.bottomMenuIndexs.index == index && this.$store.state.bottomMenuIndexs.subIndex == subIndex) {
  183. return "/static/images/bottomMenuIcon/" + bgImage + "-a.png";
  184. } else {
  185. return "/static/images/bottomMenuIcon/" + bgImage + ".png";
  186. }
  187. },
  188. // 当用户点击svg底座时,切换底部菜单显示隐藏状态。(较难理解部分,如有疑问,请联系LiuMengxiang)
  189. changeShowBottomMenusStatus(state) {
  190. // 如果接收对象不为空
  191. if (state != undefined) {
  192. // 切换底部菜单显示隐藏状态
  193. this.showBottomMenusStatus = state;
  194. // 并切换弹窗显示隐藏状态
  195. this.dialogVisibleStatus = !state;
  196. } else {
  197. // 否则直接切换底部菜单显示隐藏状态
  198. this.showBottomMenusStatus = !this.showBottomMenusStatus;
  199. }
  200. }
  201. },
  202. watch: {}
  203. };
  204. </script>
  205. <style lang="less" scoped>
  206. @borderColor: #00aaff;
  207. @topTitleMinLeft: transparent;
  208. // 底部菜单
  209. #bottomMenus {
  210. position: absolute;
  211. bottom: 20px;
  212. display: flex;
  213. flex-direction: column-reverse;
  214. align-content: center;
  215. align-items: center;
  216. width: 100%;
  217. height: 100%;
  218. -moz-user-select: none;
  219. -webkit-user-select: none;
  220. -ms-user-select: none;
  221. -khtml-user-select: none;
  222. user-select: none;
  223. overflow: hidden;
  224. // svgBox
  225. #svgBox {
  226. width: 220px;
  227. height: 70px;
  228. overflow: hidden;
  229. z-index: 2;
  230. }
  231. }
  232. // menusBox
  233. #menusBox {
  234. background-color: rgba(0, 47, 86, 0.6);
  235. z-index: 1;
  236. border: 1px solid #00aaff;
  237. position: absolute;
  238. bottom: 60px;
  239. display: flex;
  240. flex-wrap: nowrap;
  241. align-content: center;
  242. justify-content: space-evenly;
  243. align-items: center;
  244. transition: width 0.2s, height 0.5s;
  245. &::before {
  246. content: "";
  247. position: absolute;
  248. bottom: -30px;
  249. width: 100%;
  250. height: 30px;
  251. background-image: linear-gradient(to top, #00aaff, #00aaff32);
  252. clip-path: polygon(0 0, 100% 0, 50% 100%, 0 0);
  253. }
  254. }
  255. .bottomMenus {
  256. &_box {
  257. overflow: hidden;
  258. height: 155px;
  259. position: relative;
  260. background: linear-gradient(to left, #00aaff, #00aaff) left top no-repeat,
  261. linear-gradient(to bottom, #00aaff, #00aaff) left top no-repeat,
  262. linear-gradient(to left, #00aaff, #00aaff) right top no-repeat,
  263. linear-gradient(to bottom, #00aaff, #00aaff) right top no-repeat,
  264. linear-gradient(to left, #00aaff, #00aaff) left bottom no-repeat,
  265. linear-gradient(to bottom, #00aaff, #00aaff) left bottom no-repeat,
  266. linear-gradient(to left, #00aaff, #00aaff) right bottom no-repeat,
  267. linear-gradient(to left, #00aaff, #00aaff) right bottom no-repeat;
  268. background-size: 3px 21px, 21px 3px, 3px 21px, 21px 3px;
  269. display: flex;
  270. flex-wrap: nowrap;
  271. align-content: center;
  272. justify-content: space-evenly;
  273. align-items: center;
  274. flex-direction: column;
  275. &::before {
  276. content: "";
  277. position: absolute;
  278. width: 100%;
  279. height: 100%;
  280. background-color: rgba(0, 54, 179, 0.3);
  281. z-index: 9999;
  282. }
  283. &_title {
  284. width: 100%;
  285. height: 40px;
  286. display: flex;
  287. justify-content: center;
  288. align-items: center;
  289. background-image: linear-gradient(to left, @topTitleMinLeft, @borderColor, @topTitleMinLeft);
  290. font-size: 16px;
  291. font-family: pingfangSC;
  292. font-weight: 300;
  293. color: #ffffff;
  294. line-height: 60px;
  295. z-index: 99999;
  296. }
  297. &_main {
  298. width: 100%;
  299. display: flex;
  300. flex-wrap: nowrap;
  301. align-content: center;
  302. justify-content: space-evenly;
  303. align-items: center;
  304. .colBtuMenu {
  305. display: flex;
  306. flex-wrap: nowrap;
  307. align-content: center;
  308. flex-direction: column;
  309. justify-content: space-evenly;
  310. align-items: center;
  311. position: relative;
  312. cursor: pointer;
  313. z-index: 99999;
  314. &:hover {
  315. &::before {
  316. content: "";
  317. position: absolute;
  318. width: 110%;
  319. height: 110%;
  320. border-radius: 10px;
  321. z-index: 999;
  322. box-shadow: 0px 0px 5px 1px #00f5ff;
  323. }
  324. .BtuMenu {
  325. display: none;
  326. }
  327. .BtuMenu_hover {
  328. display: block;
  329. }
  330. .BtuMenu_title {
  331. color: #00f5ff;
  332. }
  333. }
  334. .colBtuMenuShadow {
  335. content: "";
  336. position: absolute;
  337. width: 110%;
  338. height: 110%;
  339. border-radius: 10px;
  340. z-index: 999;
  341. box-shadow: 0px 0px 5px 3px #00f5ff;
  342. }
  343. .BtuMenu,
  344. .BtuMenu_hover {
  345. width: 50px;
  346. height: 50px;
  347. background-repeat: no-repeat;
  348. background-size: 100% 100%;
  349. }
  350. .BtuMenu {
  351. display: block;
  352. }
  353. .BtuMenu_hover {
  354. display: none;
  355. }
  356. & > .BtuMenu_title {
  357. font-size: 14px;
  358. font-family: pingfangSC;
  359. font-weight: bold;
  360. color: #ffffff;
  361. line-height: 22px;
  362. }
  363. }
  364. }
  365. }
  366. }
  367. </style>