top.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. <template>
  2. <a-layout class="layout-top">
  3. <a-layout-header class="m-layout-header">
  4. <div>
  5. <img src="../assets/images/logoHeader.png" />
  6. <span>深圳市多元世纪信息技术股份有限公司</span>
  7. </div>
  8. <div class="m-layout-header-right">
  9. <div @click="openDrawer">
  10. <span>{{ username }},您好!</span>
  11. </div>
  12. <div class="relative">
  13. <!-- <a-input-search ref="userNameInput"
  14. class="searchInput"
  15. readonly
  16. placeholder="请输入代码/名称"
  17. @pressEnter="search">
  18. </a-input-search> -->
  19. <!-- <a-icon type="search" /> -->
  20. </div>
  21. <div class="news-container">
  22. <a-badge @click="openNotice">
  23. <svg class="icon svg-icon" aria-hidden="true">
  24. <use xlink:href="#icon-xiaoxi"></use>
  25. </svg>
  26. </a-badge>
  27. </div>
  28. <div>
  29. <a-popover v-model:visible="visible" trigger="click" placement="bottomRight">
  30. <template #content>
  31. <div v-for="item in setMenu" @click="chooseSetMenu(item.path)" :key="item.path">{{ item.name }}</div>
  32. </template>
  33. <a-avatar :size="24">
  34. <template #icon>
  35. <UserOutlined />
  36. </template>
  37. </a-avatar>
  38. </a-popover>
  39. <Setting />
  40. </div>
  41. </div>
  42. </a-layout-header>
  43. <a-layout class="middleLayout">
  44. <a-layout-sider class="m-layout-left" width="180" v-model:collapsed="collapsed" @collapse="collapse" collapsible>
  45. <a-menu theme="dark" mode="inline" class="left-menu" v-model:selectedKeys="selectedKeys" v-model:openKeys="openKeys" @click="menuClick">
  46. <a-sub-menu v-for="item in menuList" :key="item.code">
  47. <template #title>
  48. <span>
  49. <svg class="icon svg-icon" aria-hidden="true">
  50. <use :xlink:href="fontIcon(item.code)"></use>
  51. </svg>
  52. <span class="menu-item_title" v-show="!collapsed">{{ item.title }}</span>
  53. </span>
  54. </template>
  55. <a-menu-item :key="subItem.code" v-for="subItem in item.children">
  56. <span>{{ subItem.title }}</span>
  57. </a-menu-item>
  58. </a-sub-menu>
  59. </a-menu>
  60. </a-layout-sider>
  61. <a-layout-content :style="{ background: '#0E0E0F', flex: 1 }">
  62. <Drawer :title="'挂牌'" :visible="visible"></Drawer>
  63. <router-view />
  64. </a-layout-content>
  65. </a-layout>
  66. </a-layout>
  67. </template>
  68. <script lang="ts">
  69. import { UserOutlined } from '@ant-design/icons-vue';
  70. import { defineComponent, ref, provide, unref } from 'vue';
  71. import Setting from '@/views/setting/index.vue';
  72. import CapitalInfo from '@/common/components/capitalInfo/index.vue';
  73. import SecondMenu from '@/common/components/secondeMenu/index.vue';
  74. import APP from '@/services';
  75. import { initData } from '@/common/methods';
  76. import { useRouter } from 'vue-router';
  77. import { openModal } from '@/common/setup/modal/index';
  78. import Drawer from '@/common/components/drawer/index.vue';
  79. // 菜单栏
  80. const handleMenu = () => {
  81. const collapsed = ref<boolean>(false);
  82. const selectedKeys = ref<string[]>(['1-1']);
  83. const openKeys = ref<string[]>(['1']);
  84. const preOpenKeys = ref<string[]>(['1']);
  85. const menuList = APP.getRef('menus');
  86. // const menuList = [
  87. // {
  88. // key: '1',
  89. // title: '市场',
  90. // code: 'market',
  91. // children: [
  92. // {
  93. // key: '1-1',
  94. // title: '现货贸易',
  95. // code: ''
  96. // },
  97. // ],
  98. // },
  99. // {
  100. // key: '2',
  101. // title: '查询',
  102. // code: 'search',
  103. // children: [
  104. // {
  105. // key: '2-1',
  106. // title: '单据记录',
  107. // code: ''
  108. // },
  109. // {
  110. // key: '2-2',
  111. // title: '资金流水',
  112. // code: ''
  113. // },
  114. // {
  115. // key: '2-3',
  116. // title: '出入库',
  117. // code: ''
  118. // },
  119. // {
  120. // key: '2-4',
  121. // title: '登录日志',
  122. // code: ''
  123. // },
  124. // ],
  125. // },
  126. // {
  127. // key: '3',
  128. // title: '报表',
  129. // code: 'report'
  130. // },
  131. // ];
  132. const router = useRouter();
  133. // 控制菜单是否隐藏
  134. function collapse(collapsed: boolean) {
  135. if (collapsed) {
  136. preOpenKeys.value = openKeys.value;
  137. openKeys.value = [];
  138. } else {
  139. openKeys.value = preOpenKeys.value;
  140. }
  141. }
  142. // 配置是否显示下半部分
  143. function setShowBottomPart(code: string): boolean {
  144. // 显示下半部分 这里保存的是市场对应的 code
  145. const show: string[] = [''];
  146. return show.includes(code);
  147. }
  148. function menuClick(value: any) {
  149. console.log('菜单: ', value);
  150. const key = value.key;
  151. setShowBottomPart(key);
  152. router.push({ name: key });
  153. }
  154. // 一级菜单图标
  155. function fontIcon(code: string): string {
  156. let result = 'icon-jinrongfenxi';
  157. switch (code) {
  158. case 'market':
  159. result = 'icon-jinrongfenxi';
  160. break;
  161. case 'info':
  162. result = 'icon-zhangdan';
  163. break;
  164. case 'business':
  165. result = 'icon-renwu';
  166. break;
  167. case 'manage':
  168. result = 'icon-quanxian';
  169. break;
  170. case 'search':
  171. result = 'icon-chazhaojilu';
  172. break;
  173. case 'report':
  174. result = 'icon-bingtu';
  175. break;
  176. }
  177. return '#' + result;
  178. }
  179. return { collapsed, selectedKeys, menuList, openKeys, collapse, menuClick, setShowBottomPart, fontIcon };
  180. };
  181. function testAction() {
  182. const { openAction } = openModal('drawer');
  183. return { openDrawer: openAction };
  184. }
  185. // 设置
  186. const setFn = () => {
  187. const visible = ref<boolean>(false);
  188. const chooseSetupItem = ref<string>('');
  189. provide('ControlModal', chooseSetupItem);
  190. const setMenu = [
  191. // { name: '修改密码', path: 'password' },
  192. // { name: '收货地址', path: 'addresss' },
  193. // // {name: '发票', path: 'setup-password'},
  194. // { name: '手机号码绑定/解绑', path: 'phone' },
  195. // { name: '关于我们', path: 'aboutUs' },
  196. { name: '退出', path: 'logout' },
  197. ];
  198. const { openAction } = openModal('logout');
  199. function chooseSetMenu(path: string) {
  200. // chooseSetupItem.value = path;
  201. openAction();
  202. console.log(path);
  203. visible.value = false;
  204. }
  205. return { visible, setMenu, chooseSetMenu };
  206. };
  207. // 搜索
  208. const onSearch = () => {
  209. function search(value: string) {
  210. console.log(value);
  211. }
  212. return { search };
  213. };
  214. // 控制消息弹窗
  215. function controlNotice() {
  216. const { openAction } = openModal('notice');
  217. return { openNotice: openAction };
  218. }
  219. export default defineComponent({
  220. name: 'layout-top',
  221. components: {
  222. Setting,
  223. UserOutlined,
  224. CapitalInfo,
  225. SecondMenu,
  226. Drawer,
  227. },
  228. setup(props, context) {
  229. const { collapsed, selectedKeys, openKeys, menuList, collapse, menuClick, setShowBottomPart, fontIcon } = handleMenu();
  230. const router = useRouter();
  231. // 控制消息弹窗
  232. const { openNotice } = controlNotice();
  233. initData(() => {
  234. // 处理路由跳转到菜单栏里第一个对应的页面
  235. const list = unref(menuList);
  236. if (list.length && list[0].children && list[0].children.length) {
  237. // 处理修改具体某个菜单栏,主要处理页面刷新
  238. let firstIndex = 0,
  239. secondeIndex = 0;
  240. for (let i = 0; i < list.length; i++) {
  241. for (let j = 0; j < list[i].children.length; j++) {
  242. if (window.location.hash.includes(list[i].children[j].code)) {
  243. firstIndex = i;
  244. secondeIndex = j;
  245. break;
  246. }
  247. }
  248. }
  249. const code = list[firstIndex].children[secondeIndex].code;
  250. // selectedKeys.value.length = 0;
  251. // selectedKeys.value.push(code);
  252. // openKeys.value.length = 0;
  253. // openKeys.value.push(list[firstIndex].code);
  254. selectedKeys.value = [code];
  255. openKeys.value = [list[firstIndex].code];
  256. context.emit('chooseMenu', setShowBottomPart(code));
  257. // 处理页面刷新时候 引发路由乱跳的bug
  258. if (router.currentRoute.value.fullPath === '/home') {
  259. router.push(code);
  260. } else {
  261. }
  262. }
  263. });
  264. const { openDrawer } = testAction();
  265. const { visible, setMenu, chooseSetMenu } = setFn();
  266. const username = APP.get('username');
  267. const { search } = onSearch();
  268. const searchName = ref<string[]>(['']);
  269. return {
  270. collapsed,
  271. collapse,
  272. selectedKeys,
  273. openKeys,
  274. menuClick,
  275. username,
  276. menuList,
  277. visible,
  278. setMenu,
  279. chooseSetMenu,
  280. fontIcon,
  281. openNotice,
  282. openDrawer,
  283. };
  284. },
  285. });
  286. </script>
  287. <style lang="less">
  288. .layout-top {
  289. .flex;
  290. width: 100%;
  291. height: 100%;
  292. flex-direction: column;
  293. .m-layout-header {
  294. width: 100%;
  295. height: 40px;
  296. line-height: 40px;
  297. background: @m-grey0;
  298. color: @m-grey1;
  299. padding: 0 20px;
  300. .flex();
  301. justify-content: space-between;
  302. img {
  303. margin-right: 16px;
  304. width: 20px;
  305. height: 20px;
  306. }
  307. .searchInput.ant-input-affix-wrapper {
  308. width: 240px;
  309. height: 30px;
  310. line-height: 30px;
  311. font-size: 14px;
  312. background: @m-grey9;
  313. border: 0;
  314. vertical-align: middle;
  315. padding-left: 40px;
  316. position: relative;
  317. .rounded-corners(15px);
  318. .ant-input {
  319. background: @m-grey9;
  320. color: @m-white0;
  321. }
  322. .ant-input-suffix {
  323. margin-left: -215px;
  324. .ant-input-search-icon {
  325. color: @m-grey10;
  326. }
  327. }
  328. }
  329. // .relative {
  330. // position: relative;
  331. // .a-icon {
  332. // font-size: 14px;
  333. // .position(absolute, 50%, auto, auto, 10px);
  334. // margin-top: -7px;
  335. // color: @m-grey10;
  336. // z-index: 10;
  337. // }
  338. // }
  339. .m-layout-header-right {
  340. .flex();
  341. .news-container {
  342. padding-left: 10px;
  343. padding-right: 16px;
  344. .ant-badge {
  345. margin-top: 7px;
  346. cursor: pointer;
  347. > svg {
  348. font-size: 24px;
  349. }
  350. .ant-badge-dot {
  351. box-shadow: 0 0 0 1px @m-red0;
  352. }
  353. }
  354. }
  355. .ant-avatar-icon {
  356. margin-top: -3px;
  357. }
  358. }
  359. }
  360. .middleLayout {
  361. flex: 1;
  362. width: 100%;
  363. .inlineflex;
  364. border-bottom: 1px solid @m-black2;
  365. .m-layout-left {
  366. height: 100%;
  367. background: @m-black4;
  368. .ant-layout-sider-children {
  369. ul.ant-menu.ant-menu-inline {
  370. li.ant-menu-submenu {
  371. padding-bottom: 0;
  372. .ant-menu-submenu-title {
  373. color: @m-grey2;
  374. font-size: 16px;
  375. height: 60px;
  376. line-height: 60px;
  377. margin-top: 0;
  378. margin-bottom: 0;
  379. padding: 5px 0;
  380. .icon {
  381. font-size: 20px;
  382. }
  383. .menu-item_title {
  384. display: inline-block;
  385. font-size: 16px;
  386. margin-left: 15px;
  387. }
  388. }
  389. .ant-menu-sub {
  390. .ant-menu-item {
  391. padding-left: 60px !important;
  392. margin-top: 5px;
  393. margin-bottom: 5px;
  394. }
  395. }
  396. }
  397. li.ant-menu-submenu-open {
  398. .ant-menu-submenu-title {
  399. color: @m-white0;
  400. .icon {
  401. color: @m-white0;
  402. }
  403. }
  404. .ant-menu-sub {
  405. .ant-menu-item.ant-menu-item-selected {
  406. background-color: @m-blue0;
  407. }
  408. }
  409. }
  410. }
  411. }
  412. .ant-layout-sider-trigger {
  413. width: 100%;
  414. height: 40px;
  415. line-height: 40px;
  416. background: @m-black0;
  417. position: absolute;
  418. }
  419. }
  420. .ant-menu-vertical {
  421. .ant-menu-submenu-vertical {
  422. height: 60px;
  423. line-height: 60px;
  424. padding: 5px 0;
  425. .ant-menu-submenu-title {
  426. height: 50px;
  427. line-height: 50px;
  428. .icon {
  429. font-size: 20px;
  430. }
  431. }
  432. }
  433. .ant-menu-submenu {
  434. .ant-menu-submenu-title {
  435. .menu-item_title {
  436. display: none;
  437. }
  438. }
  439. }
  440. }
  441. }
  442. .bottomLayout {
  443. width: 100%;
  444. flex: none;
  445. height: @bottomHeight;
  446. .inlineflex;
  447. }
  448. }
  449. </style>